--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bundle_internal.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <ttrace.h>
+
+#include <memory>
+#include <utility>
+
+#include "app_request.h"
+#include "app_signal.h"
+#include "aul_api.h"
+#include "aul_app_com.h"
+#include "aul_error.h"
+#include "aul_util.h"
+#include "key.h"
+#include "launch.h"
+
+namespace aul {
+namespace internal {
+
+AppRequest::AppRequest(int cmd, uid_t uid) : cmd_(cmd), uid_(uid) {
+ SetUid(uid);
+}
+
+AppRequest::AppRequest(int cmd) : cmd_(cmd), uid_(getuid()) {
+ SetUid(uid_);
+}
+
+AppRequest& AppRequest::With(tizen_base::Bundle b) {
+ bundle_ = std::move(b);
+ ClearInternalKey();
+ SetUid(uid_);
+ return *this;
+}
+
+AppRequest& AppRequest::With(bundle* b) {
+ if (b == nullptr)
+ return *this;
+ bundle_ = tizen_base::Bundle(b, false, false);
+ ClearInternalKey();
+ SetUid(uid_);
+ return *this;
+}
+
+AppRequest& AppRequest::SetAppId(const std::string& app_id) {
+ bundle_.Delete(AUL_K_APPID);
+ bundle_.Add(AUL_K_APPID, app_id);
+ return *this;
+}
+
+AppRequest& AppRequest::SetInstId(const std::string& inst_id) {
+ bundle_.Delete(AUL_K_INSTANCE_ID);
+ bundle_.Add(AUL_K_INSTANCE_ID, inst_id);
+ return *this;
+}
+
+AppRequest& AppRequest::SetAppIdAsPid(pid_t pid) {
+ char buf[MAX_PID_STR_BUFSZ];
+ snprintf(buf, sizeof(buf), "%d", pid);
+ bundle_.Delete(AUL_K_APPID);
+ bundle_.Add(AUL_K_APPID, buf);
+ return *this;
+}
+
+AppRequest& AppRequest::SetPid(pid_t pid) {
+ char buf[MAX_PID_STR_BUFSZ];
+ snprintf(buf, sizeof(buf), "%d", pid);
+ bundle_.Delete(AUL_K_PID);
+ bundle_.Add(AUL_K_PID, buf);
+ return *this;
+}
+
+int AppRequest::Send(int opt) {
+ traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "AUL:REQ_TO_PAD");
+ std::string appid = bundle_.GetString(AUL_K_APPID);
+ _W("Request cmd(%d): appid(%s), target_uid(%u)",
+ cmd_, appid.c_str(), uid_);
+
+ SetTime();
+ switch (cmd_) {
+ case APP_SEND_LAUNCH_REQUEST:
+ case APP_SEND_LAUNCH_REQUEST_SYNC:
+ case APP_SEND_RESUME_REQUEST:
+ opt |= AUL_SOCK_ASYNC;
+ break;
+ }
+
+ int ret = aul_sock_send_bundle(AUL_UTIL_PID, uid_, cmd_,
+ bundle_.GetHandle(), opt);
+ if (ret < 0)
+ ret = aul_error_convert(ret);
+ _W("Request cmd(%d): result(%d)", cmd_, ret);
+ if (ret == AUL_R_LOCAL)
+ ret = app_request_local(cmd_, bundle_.GetHandle());
+ traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
+ return ret;
+}
+
+int AppRequest::SendSimply(int opt) {
+ _W("Request cmd(%d): target_uid(%u)", cmd_, uid_);
+ int ret = aul_sock_send_bundle(AUL_UTIL_PID, uid_, cmd_,
+ bundle_.GetHandle(), opt);
+ if (ret < 0)
+ ret = aul_error_convert(ret);
+ _W("Request cmd(%d): result(%d)", cmd_, ret);
+ return ret;
+}
+
+int AppRequest::SendCmdOnly(int opt) {
+ _W("Request cmd(%d): target_uid(%u)", cmd_, uid_);
+ int ret = aul_sock_send_raw(AUL_UTIL_PID, uid_, cmd_, nullptr, 0, opt);
+ _W("Request cmd(%d): result(%d)", cmd_, ret);
+ return ret;
+}
+
+void AppRequest::ClearInternalKey() {
+ bundle_.Delete(AUL_K_CALLER_PID);
+ bundle_.Delete(AUL_K_APPID);
+ bundle_.Delete(AUL_K_WAIT_RESULT);
+ bundle_.Delete(AUL_K_SEND_RESULT);
+ bundle_.Delete(AUL_K_ARGV0);
+}
+
+void AppRequest::SetTime() {
+ struct timespec start;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ char tmp[MAX_LOCAL_BUFSZ];
+ snprintf(tmp, sizeof(tmp), "%ld/%ld", start.tv_sec, start.tv_nsec);
+ bundle_.Delete(AUL_K_STARTTIME);
+ bundle_.Add(AUL_K_STARTTIME, tmp);
+}
+
+void AppRequest::SetUid(uid_t uid) {
+ char buf[MAX_PID_STR_BUFSZ];
+ snprintf(buf, sizeof(buf), "%d", uid);
+ bundle_.Delete(AUL_K_TARGET_UID);
+ bundle_.Add(AUL_K_TARGET_UID, buf);
+}
+
+} // namespace internal
+} // namespace aul
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APP_REQUEST_H_
+#define APP_REQUEST_H_
+
+#include <bundle_cpp.h>
+#include <bundle.h>
+#include <string>
+
+#include "aul.h"
+#include "aul_sock.h"
+
+namespace aul {
+namespace internal {
+
+class AppRequest {
+ public:
+ AppRequest(int cmd, uid_t uid);
+ AppRequest(int cmd);
+
+ AppRequest& With(tizen_base::Bundle b);
+ AppRequest& With(bundle* b);
+ AppRequest& SetAppId(const std::string& app_id);
+ AppRequest& SetInstId(const std::string& inst_id);
+ AppRequest& SetAppIdAsPid(pid_t pid);
+ AppRequest& SetPid(pid_t pid);
+ int Send(int opt = AUL_SOCK_QUEUE);
+ int SendSimply(int opt = AUL_SOCK_NONE);
+ int SendCmdOnly(int opt = AUL_SOCK_NONE);
+
+ private:
+ void ClearInternalKey();
+ void SetTime();
+ void SetUid(uid_t uid);
+
+ private:
+ int cmd_;
+ uid_t uid_;
+ tizen_base::Bundle bundle_;
+};
+
+} // namespace internal
+} // namespace aul
+
+#endif // APP_REQUEST_H_
\ No newline at end of file
* limitations under the License.
*/
-#include <bundle_cpp.h>
#include <bundle_internal.h>
#include <ctype.h>
#include <dirent.h>
#include <memory>
+#include "app_request.h"
#include "app_signal.h"
#include "aul.h"
#include "aul_api.h"
#include "key.h"
#include "launch.h"
+using namespace aul::internal;
+
namespace {
constexpr const int TEP_ISMOUNT_MAX_RETRY_CNT = 20;
-class AppRequest {
- public:
- AppRequest(int cmd, uid_t uid) : cmd_(cmd), uid_(uid) {
- SetUid(uid);
- }
-
- AppRequest(int cmd) : cmd_(cmd), uid_(getuid()) {
- SetUid(uid_);
- }
-
- AppRequest& With(tizen_base::Bundle b) {
- bundle_ = std::move(b);
- ClearInternalKey();
- SetUid(uid_);
- return *this;
- }
-
- AppRequest& With(bundle* b) {
- if (b == nullptr)
- return *this;
- bundle_ = tizen_base::Bundle(b, false, false);
- ClearInternalKey();
- SetUid(uid_);
- return *this;
- }
-
- AppRequest& SetAppId(const std::string& app_id) {
- bundle_.Delete(AUL_K_APPID);
- bundle_.Add(AUL_K_APPID, app_id);
- return *this;
- }
-
- AppRequest& SetInstId(const std::string& inst_id) {
- bundle_.Delete(AUL_K_INSTANCE_ID);
- bundle_.Add(AUL_K_INSTANCE_ID, inst_id);
- return *this;
- }
-
- AppRequest& SetAppIdAsPid(pid_t pid) {
- char buf[MAX_PID_STR_BUFSZ];
- snprintf(buf, sizeof(buf), "%d", pid);
- bundle_.Delete(AUL_K_APPID);
- bundle_.Add(AUL_K_APPID, buf);
- return *this;
- }
-
- AppRequest& SetPid(pid_t pid) {
- char buf[MAX_PID_STR_BUFSZ];
- snprintf(buf, sizeof(buf), "%d", pid);
- bundle_.Delete(AUL_K_PID);
- bundle_.Add(AUL_K_PID, buf);
- return *this;
- }
-
- int Send(int opt = AUL_SOCK_QUEUE) {
- traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "AUL:REQ_TO_PAD");
- std::string appid = bundle_.GetString(AUL_K_APPID);
- _W("Request cmd(%d): appid(%s), target_uid(%u)",
- cmd_, appid.c_str(), uid_);
-
- SetTime();
- switch (cmd_) {
- case APP_SEND_LAUNCH_REQUEST:
- case APP_SEND_LAUNCH_REQUEST_SYNC:
- case APP_SEND_RESUME_REQUEST:
- opt |= AUL_SOCK_ASYNC;
- break;
- }
-
- int ret = aul_sock_send_bundle(AUL_UTIL_PID, uid_, cmd_,
- bundle_.GetHandle(), opt);
- if (ret < 0)
- ret = aul_error_convert(ret);
- _W("Request cmd(%d): result(%d)", cmd_, ret);
- if (ret == AUL_R_LOCAL)
- ret = app_request_local(cmd_, bundle_.GetHandle());
- traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
- return ret;
- }
-
- int SendSimply(int opt = AUL_SOCK_NONE) {
- _W("Request cmd(%d): target_uid(%u)", cmd_, uid_);
- int ret = aul_sock_send_bundle(AUL_UTIL_PID, uid_, cmd_,
- bundle_.GetHandle(), opt);
- if (ret < 0)
- ret = aul_error_convert(ret);
- _W("Request cmd(%d): result(%d)", cmd_, ret);
- return ret;
- }
-
- int SendCmdOnly(int opt = AUL_SOCK_NONE) {
- _W("Request cmd(%d): target_uid(%u)", cmd_, uid_);
- int ret = aul_sock_send_raw(AUL_UTIL_PID, uid_, cmd_, nullptr, 0, opt);
- _W("Request cmd(%d): result(%d)", cmd_, ret);
- return ret;
- }
-
- private:
- void ClearInternalKey() {
- bundle_.Delete(AUL_K_CALLER_PID);
- bundle_.Delete(AUL_K_APPID);
- bundle_.Delete(AUL_K_WAIT_RESULT);
- bundle_.Delete(AUL_K_SEND_RESULT);
- bundle_.Delete(AUL_K_ARGV0);
- }
-
- void SetTime() {
- struct timespec start;
- clock_gettime(CLOCK_MONOTONIC, &start);
- char tmp[MAX_LOCAL_BUFSZ];
- snprintf(tmp, sizeof(tmp), "%ld/%ld", start.tv_sec, start.tv_nsec);
- bundle_.Delete(AUL_K_STARTTIME);
- bundle_.Add(AUL_K_STARTTIME, tmp);
- }
-
- void SetUid(uid_t uid) {
- char buf[MAX_PID_STR_BUFSZ];
- snprintf(buf, sizeof(buf), "%d", uid);
- bundle_.Delete(AUL_K_TARGET_UID);
- bundle_.Add(AUL_K_TARGET_UID, buf);
- }
-
- private:
- int cmd_;
- uid_t uid_;
- tizen_base::Bundle bundle_;
-};
-
int aul_initialized = 0;
int aul_fd;
void* window_object = nullptr;
}
}
-extern "C" int app_request_to_launchpad(int cmd, const char* appid,
- bundle* kb) {
- return app_request_to_launchpad_for_uid(cmd, appid, kb, getuid());
-}
-
extern "C" int app_request_to_launchpad_for_uid(int cmd, const char* appid,
bundle* kb, uid_t uid) {
return AppRequest(cmd, uid)
int app_send_cmd_for_uid(int pid, uid_t uid, int cmd, bundle *kb);
int app_send_cmd_with_noreply(int pid, int cmd, bundle *kb);
int app_send_cmd_to_launchpad(const char *pad_type, uid_t uid, int cmd, bundle *kb);
-int app_request_to_launchpad(int cmd, const char *pkgname, bundle *kb);
int app_request_to_launchpad_for_uid(int cmd, const char *pkgname, bundle *kb, uid_t uid);
int app_result(int cmd, bundle *kb, int launched_pid);
+++ /dev/null
-/*
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <time.h>
-#include <glib.h>
-#include <gio/gio.h>
-#include <bundle_internal.h>
-#include <uuid.h>
-
-#include "aul.h"
-#include "aul_api.h"
-#include "aul_error.h"
-#include "aul_sock.h"
-#include "aul_svc.h"
-#include "aul_svc_priv_key.h"
-#include "aul_util.h"
-#include "launch.h"
-
-typedef struct _aul_error_info_t {
- GIOChannel *io;
- char *seq_num;
- bundle *b;
- int cmd;
- void (*error_cb)(int res, void *user_data);
- void *user_data;
-} aul_error_info_t;
-
-typedef struct _aul_reply_info_t {
- char *seq_num;
- int launched_pid;
- void (*reply_cb)(bundle *b, int is_cancel, void *user_data);
- void *user_data;
- void (*caller_cb)(int launched_pid, void *user_data);
- void *caller_data;
-} aul_reply_info_t;
-
-static pthread_mutex_t __aul_mutex = PTHREAD_MUTEX_INITIALIZER;
-static GList *__reply_info_list;
-
-static int __rand(int n)
-{
- unsigned int seed = time(NULL) + n;
-
- return rand_r(&seed);
-}
-
-static char *__gen_seq_num(void)
-{
- static int num;
- char buf[MAX_LOCAL_BUFSZ];
-
- g_atomic_int_inc(&num);
- snprintf(buf, sizeof(buf), "%d@%d", __rand(num), num);
-
- return strdup(buf);
-}
-
-static void __destroy_aul_error_info(aul_error_info_t *info)
-{
- if (!info)
- return;
-
- if (info->io)
- g_io_channel_unref(info->io);
-
- if (info->b)
- bundle_free(info->b);
-
- if (info->seq_num)
- free(info->seq_num);
-
- free(info);
-}
-
-static aul_error_info_t *__create_aul_error_info(const char *seq_num,
- bundle *b, int cmd, void (*error_cb)(int, void *),
- void *user_data)
-{
- aul_error_info_t *info;
-
- info = calloc(1, sizeof(aul_error_info_t));
- if (!info) {
- _E("Out of memory");
- return NULL;
- }
-
- info->seq_num = strdup(seq_num);
- if (!info->seq_num) {
- _E("Failed to duplicate seq num");
- __destroy_aul_error_info(info);
- return NULL;
- }
-
- info->b = bundle_dup(b);
- if (!info->b) {
- _E("Failed to duplicate bundle");
- __destroy_aul_error_info(info);
- return NULL;
- }
-
- info->cmd = cmd;
- info->error_cb = error_cb;
- info->user_data = user_data;
-
- return info;
-}
-
-static void __destroy_aul_reply_info(gpointer data)
-{
- aul_reply_info_t *info = (aul_reply_info_t *)data;
-
- if (!info)
- return;
-
- if (info->seq_num)
- free(info->seq_num);
-
- free(info);
-}
-
-static aul_reply_info_t *__create_aul_reply_info(int pid,
- const char *seq_num,
- void (*reply_cb)(bundle *, int, void *),
- void *user_data)
-{
- aul_reply_info_t *info;
-
- info = calloc(1, sizeof(aul_reply_info_t));
- if (!info) {
- _E("Out of memory");
- return NULL;
- }
-
- info->seq_num = strdup(seq_num);
- if (!info->seq_num) {
- _E("Failed to duplicate seq num");
- __destroy_aul_reply_info(info);
- return NULL;
- }
-
- info->launched_pid = pid;
- info->reply_cb = reply_cb;
- info->user_data = user_data;
-
- return info;
-}
-
-static void __update_aul_reply_info(const char *seq_num,
- int launched_pid)
-{
- aul_reply_info_t *info;
- GList *iter;
-
- if (!seq_num)
- return;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- if (!strcmp(info->seq_num, seq_num)) {
- info->launched_pid = launched_pid;
- break;
- }
- iter = g_list_next(iter);
- }
- pthread_mutex_unlock(&__aul_mutex);
-}
-
-static void __push_aul_reply_info(aul_reply_info_t *info)
-{
- if (!info)
- return;
-
- pthread_mutex_lock(&__aul_mutex);
- __reply_info_list = g_list_prepend(__reply_info_list, info);
- pthread_mutex_unlock(&__aul_mutex);
-}
-
-static aul_reply_info_t *__pop_aul_reply_info(const char *seq_num)
-{
- aul_reply_info_t *info;
- GList *iter;
-
- if (!seq_num)
- return NULL;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- if (!strcmp(info->seq_num, seq_num)) {
- __reply_info_list = g_list_remove(__reply_info_list,
- info);
- pthread_mutex_unlock(&__aul_mutex);
- return info;
- }
- iter = g_list_next(iter);
- }
- pthread_mutex_unlock(&__aul_mutex);
-
- return NULL;
-}
-
-static int __invoke_aul_reply_cb(bundle *kb, int is_cancel,
- int launched_pid)
-{
- aul_reply_info_t *new_info;
- aul_reply_info_t *info;
- const char *fwdpid_str;
- const char *seq_num;
-
- if (!kb) {
- _E("Invalid parameter");
- return -1;
- }
-
- if (launched_pid < 0) {
- _E("Received pid(%d)", launched_pid);
- return -1;
- }
-
- seq_num = bundle_get_val(kb, AUL_K_SEQ_NUM);
- if (!seq_num) {
- _E("Failed to get seq num");
- return -1;
- }
-
- info = __pop_aul_reply_info(seq_num);
- if (!info) {
- _E("Failed to find reply info");
- return -1;
- }
-
- if (!info->reply_cb) {
- _E("Reply callback function is nullptr");
- return -1;
- }
-
- fwdpid_str = bundle_get_val(kb, AUL_K_FWD_CALLEE_PID);
- if (is_cancel == 1 && fwdpid_str) {
- launched_pid = atoi(fwdpid_str);
- new_info = __create_aul_reply_info(launched_pid,
- seq_num, info->reply_cb,
- info->user_data);
- if (new_info)
- __push_aul_reply_info(new_info);
-
- if (info->caller_cb)
- info->caller_cb(launched_pid, info->caller_data);
-
- __destroy_aul_reply_info(info);
- _W("Change reply info. fwd pid: %d", launched_pid);
- return 0;
- }
-
- info->reply_cb(kb, is_cancel, info->user_data);
- __destroy_aul_reply_info(info);
-
- return 0;
-}
-
-static int __get_caller_pid(bundle *kb)
-{
- const char *pid_str;
- int pid;
-
- pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
- if (!pid_str)
- pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
-
- if (pid_str == NULL)
- return -1;
-
- pid = atoi(pid_str);
- if (pid <= 1)
- return -1;
-
- return pid;
-}
-
-int app_result(int cmd, bundle *kb, int launched_pid)
-{
- switch (cmd) {
- case APP_RESULT:
- __invoke_aul_reply_cb(kb, 0, launched_pid);
- break;
- case APP_CANCEL:
- __invoke_aul_reply_cb(kb, 1, launched_pid);
- break;
- }
-
- return 0;
-}
-
-static int __launch_app_with_result(int cmd, const char *appid, bundle *kb,
- void (*callback)(bundle *, int, void *), void *data, uid_t uid)
-{
- int ret;
- char *seq_num;
- aul_reply_info_t *info;
-
- if (!aul_is_initialized()) {
- if (aul_launch_init(NULL, NULL) < 0)
- return AUL_R_ENOINIT;
- }
-
- if (appid == NULL || callback == NULL || kb == NULL)
- return AUL_R_EINVAL;
-
- seq_num = __gen_seq_num();
- if (seq_num == NULL) {
- _E("Out of memory");
- return AUL_R_ERROR;
- }
-
- bundle_del(kb, AUL_K_SEQ_NUM);
- bundle_add(kb, AUL_K_SEQ_NUM, seq_num);
-
- info = __create_aul_reply_info(-1, seq_num, callback, data);
- if (info)
- __push_aul_reply_info(info);
-
- ret = app_request_to_launchpad_for_uid(cmd, appid, kb, uid);
- if (ret > 0) {
- __update_aul_reply_info(seq_num, ret);
- } else {
- info = __pop_aul_reply_info(seq_num);
- if (info)
- __destroy_aul_reply_info(info);
- }
- free(seq_num);
-
- return ret;
-}
-
-API int aul_launch_app_with_result(const char *pkgname, bundle *kb,
- void (*cbfunc) (bundle *, int, void *),
- void *data)
-{
- return __launch_app_with_result(APP_START_RES, pkgname, kb, cbfunc,
- data, getuid());
-}
-
-API int aul_launch_app_with_result_for_uid(const char *pkgname, bundle *kb,
- void (*cbfunc) (bundle *, int, void *), void *data, uid_t uid)
-{
- return __launch_app_with_result(APP_START_RES, pkgname, kb, cbfunc,
- data, uid);
-}
-
-static int __set_caller_info(bundle *kb)
-{
- const char *caller_pid;
- const char *caller_uid;
-
- caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
- if (caller_pid == NULL) {
- _E("Failed to get caller pid");
- return AUL_R_EINVAL;
- }
-
- caller_uid = bundle_get_val(kb, AUL_K_CALLER_UID);
- if (caller_uid == NULL) {
- _E("Failed to get caller uid");
- return AUL_R_EINVAL;
- }
-
- bundle_del(kb, AUL_K_ORG_CALLER_PID);
- bundle_add(kb, AUL_K_ORG_CALLER_PID, caller_pid);
- bundle_del(kb, AUL_K_ORG_CALLER_UID);
- bundle_add(kb, AUL_K_ORG_CALLER_UID, caller_uid);
-
- return AUL_R_OK;
-}
-
-void aul_set_instance_info(const char *app_id, bundle *kb)
-{
- const char *component_id;
- char buf[1024];
- char uuid[37];
- uuid_t u;
-
- uuid_generate(u);
- uuid_unparse(u, uuid);
-
- component_id = bundle_get_val(kb, AUL_K_COMPONENT_ID);
- if (component_id) {
- snprintf(buf, sizeof(buf), "%s:%s:%s",
- uuid, app_id, component_id);
- } else {
- snprintf(buf, sizeof(buf), "%s:%s", uuid, app_id);
- }
-
- bundle_del(kb, AUL_K_INSTANCE_ID);
- bundle_add(kb, AUL_K_INSTANCE_ID, buf);
-}
-
-API int aul_forward_app(const char* pkgname, bundle *kb)
-{
- int ret;
- bundle *dupb;
- bundle *outb;
- char tmp_pid[MAX_PID_STR_BUFSZ];
- const char *launch_mode;
-
- if (pkgname == NULL || kb == NULL)
- return AUL_R_EINVAL;
-
- if (__set_caller_info(kb) < 0)
- return AUL_R_EINVAL;
-
- bundle_del(kb, AUL_SVC_K_CAN_BE_LEADER);
- bundle_del(kb, AUL_SVC_K_REROUTE);
- bundle_del(kb, AUL_SVC_K_RECYCLE);
-
- launch_mode = bundle_get_val(kb, AUL_SVC_K_LAUNCH_MODE);
- if (launch_mode && !strcmp(launch_mode, "group"))
- aul_set_instance_info(pkgname, kb);
-
- dupb = bundle_dup(kb);
- if (dupb == NULL) {
- _E("bundle duplicate fail");
- return AUL_R_EINVAL;
- }
-
- if (bundle_get_val(kb, AUL_K_WAIT_RESULT) != NULL) {
- ret = app_request_to_launchpad(APP_START_RES, pkgname, kb);
- if (ret < 0)
- goto end;
- } else {
- ret = app_request_to_launchpad(APP_START, pkgname, kb);
- goto end;
- }
-
- snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", ret);
-
- ret = aul_create_result_bundle(dupb, &outb);
- if (ret < 0)
- goto end;
-
- bundle_del(outb, AUL_K_FWD_CALLEE_PID);
- bundle_add(outb, AUL_K_FWD_CALLEE_PID, tmp_pid);
-
- ret = aul_send_result(outb, 1);
-
- bundle_free(outb);
-end:
- bundle_free(dupb);
-
- return ret;
-}
-
-API int aul_create_result_bundle(bundle *inb, bundle **outb)
-{
- const char *pid_str;
- const char *num_str;
- const char *uid_str;
-
- *outb = NULL;
-
- if (inb == NULL) {
- _E("return msg create fail");
- return AUL_R_EINVAL;
- }
-
- *outb = bundle_create();
- if (*outb == NULL) {
- _E("return msg create fail");
- return AUL_R_ERROR;
- }
-
- if (bundle_get_val(inb, AUL_K_WAIT_RESULT) != NULL) {
- bundle_add(*outb, AUL_K_SEND_RESULT, "1");
- _D("original msg is msg with result");
- } else {
- _D("original msg is not msg with result");
- }
-
- uid_str = bundle_get_val(inb, AUL_K_ORG_CALLER_UID);
- if (uid_str == NULL)
- uid_str = bundle_get_val(inb, AUL_K_CALLER_UID);
-
- if (uid_str == NULL) {
- _E("Failed to find caller uid");
- bundle_free(*outb);
- *outb = NULL;
- return AUL_R_EINVAL;
- }
- bundle_add(*outb, AUL_K_ORG_CALLER_UID, uid_str);
-
- pid_str = bundle_get_val(inb, AUL_K_ORG_CALLER_PID);
- if (pid_str) {
- bundle_add(*outb, AUL_K_ORG_CALLER_PID, pid_str);
- goto end;
- }
-
- pid_str = bundle_get_val(inb, AUL_K_CALLER_PID);
- if (pid_str == NULL) {
- _E("original msg does not have caller pid");
- bundle_free(*outb);
- *outb = NULL;
- return AUL_R_EINVAL;
- }
- bundle_add(*outb, AUL_K_CALLER_PID, pid_str);
-
-end:
- num_str = bundle_get_val(inb, AUL_K_SEQ_NUM);
- if (num_str == NULL) {
- _E("original msg does not have seq num");
- bundle_free(*outb);
- *outb = NULL;
- return AUL_R_ECANCELED;
- }
- bundle_add(*outb, AUL_K_SEQ_NUM, num_str);
-
- return AUL_R_OK;
-}
-
-int aul_send_result(bundle *kb, int is_cancel)
-{
- int pid;
- int ret;
- int callee_pid;
- int callee_pgid;
- char callee_appid[256];
- char tmp_pid[MAX_PID_STR_BUFSZ];
-
- if ((pid = __get_caller_pid(kb)) < 0)
- return AUL_R_EINVAL;
-
- _D("caller pid : %d", pid);
-
- if (bundle_get_val(kb, AUL_K_SEND_RESULT) == NULL) {
- _D("original msg is not msg with result");
- return AUL_R_OK;
- }
-
- callee_pid = getpid();
- callee_pgid = getpgid(callee_pid);
- snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", callee_pgid);
- bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
-
- ret = aul_app_get_appid_bypid(callee_pid, callee_appid,
- sizeof(callee_appid));
- if (ret == 0)
- bundle_add(kb, AUL_K_CALLEE_APPID, callee_appid);
- else
- _W("fail(%d) to get callee appid by pid", ret);
-
- ret = app_send_cmd_with_noreply(AUL_UTIL_PID,
- (is_cancel == 1) ? APP_CANCEL : APP_RESULT, kb);
- _D("app_send_cmd_with_noreply : %d", ret);
-
- return ret;
-}
-
-API int aul_subapp_terminate_request_pid(int pid)
-{
- char pid_str[MAX_PID_STR_BUFSZ];
- aul_reply_info_t *info;
- GList *iter;
- int ret;
-
- if (pid <= 0)
- return AUL_R_EINVAL;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- iter = g_list_next(iter);
- if (info->launched_pid == pid) {
- __reply_info_list = g_list_remove(__reply_info_list,
- info);
- __destroy_aul_reply_info(info);
- }
- }
- pthread_mutex_unlock(&__aul_mutex);
-
- snprintf(pid_str, MAX_PID_STR_BUFSZ, "%d", pid);
- ret = app_request_to_launchpad(APP_TERM_REQ_BY_PID, pid_str, NULL);
- return ret;
-}
-
-int aul_subapp_terminate_request(const char *instance_id, int pid)
-{
- aul_reply_info_t *info;
- GList *iter;
-
- if (pid <= 0)
- return AUL_R_EINVAL;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- iter = g_list_next(iter);
- if (info->launched_pid == pid) {
- __reply_info_list = g_list_remove(__reply_info_list,
- info);
- __destroy_aul_reply_info(info);
- }
- }
- pthread_mutex_unlock(&__aul_mutex);
-
- return aul_terminate_instance_async(instance_id, pid);
-}
-
-API int aul_add_caller_cb(int pid, void (*caller_cb)(int, void *),
- void *data)
-{
- aul_reply_info_t *info;
- GList *iter;
-
- if (pid <= 0)
- return AUL_R_EINVAL;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- if (info->launched_pid == pid &&
- !info->caller_cb) {
- info->caller_cb = caller_cb;
- info->caller_data = data;
- pthread_mutex_unlock(&__aul_mutex);
- return AUL_R_OK;
- }
- iter = g_list_next(iter);
- }
- pthread_mutex_unlock(&__aul_mutex);
-
- return AUL_R_ERROR;
-}
-
-API int aul_remove_caller_cb(int pid, void *data)
-{
- aul_reply_info_t *info;
- GList *iter;
-
- if (pid <= 0)
- return AUL_R_EINVAL;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- if (info->launched_pid == pid &&
- info->caller_data == data) {
- info->caller_cb = NULL;
- info->caller_data = NULL;
- pthread_mutex_unlock(&__aul_mutex);
- return AUL_R_OK;
- }
- iter = g_list_next(iter);
- }
- pthread_mutex_unlock(&__aul_mutex);
-
- return AUL_R_ERROR;
-}
-
-static gboolean __invoke_caller_cb(gpointer data)
-{
- aul_reply_info_t *info = (aul_reply_info_t *)data;
-
- if (info && info->caller_cb)
- info->caller_cb(info->launched_pid, info->caller_data);
-
- __destroy_aul_reply_info(info);
-
- return G_SOURCE_REMOVE;
-}
-
-API int aul_invoke_caller_cb(void *data)
-{
- aul_reply_info_t *new_info;
- aul_reply_info_t *info;
- GList *iter;
-
- pthread_mutex_lock(&__aul_mutex);
- iter = __reply_info_list;
- while (iter) {
- info = (aul_reply_info_t *)iter->data;
- if (info->caller_data == data) {
- new_info = __create_aul_reply_info(
- info->launched_pid,
- info->seq_num,
- info->reply_cb,
- info->user_data);
- if (!new_info) {
- _E("Out of memory");
- break;
- }
-
- new_info->caller_cb = info->caller_cb;
- new_info->caller_data = info->caller_data;
-
- g_idle_add_full(G_PRIORITY_DEFAULT,
- __invoke_caller_cb,
- new_info, NULL);
- break;
- }
- iter = g_list_next(iter);
-
- }
- pthread_mutex_unlock(&__aul_mutex);
-
- return 0;
-}
-
-API int aul_launch_app_with_result_async(const char *appid, bundle *b,
- void (*callback)(bundle *, int, void *), void *data)
-{
- return __launch_app_with_result(APP_START_RES_ASYNC, appid, b, callback,
- data, getuid());
-}
-
-API int aul_launch_app_with_result_async_for_uid(const char *appid, bundle *b,
- void (*callback)(bundle *, int, void *), void *data, uid_t uid)
-{
- return __launch_app_with_result(APP_START_RES_ASYNC, appid, b, callback,
- data, uid);
-}
-
-static gboolean __aul_error_handler(GIOChannel *io,
- GIOCondition cond, gpointer user_data)
-{
- int fd = g_io_channel_unix_get_fd(io);
- aul_error_info_t *info = (aul_error_info_t *)user_data;
- aul_reply_info_t *r_info;
- int res;
-
- if (!info) {
- _E("Critical error!");
- return G_SOURCE_REMOVE;
- }
-
- res = aul_sock_recv_result_with_fd(fd);
- if (res < 1) {
- res = aul_error_convert(res);
- if (res == AUL_R_LOCAL)
- res = app_request_local(info->cmd, info->b);
- } else {
- __update_aul_reply_info(info->seq_num, res);
- }
-
- _W("Sequence(%s), result(%d)", info->seq_num, res);
-
- if (info->error_cb) {
- info->error_cb(res, info->user_data);
- info->error_cb = NULL;
- }
-
- if (res < 1) {
- r_info = __pop_aul_reply_info(info->seq_num);
- if (r_info)
- __destroy_aul_reply_info(r_info);
- }
-
- __destroy_aul_error_info(info);
-
- return G_SOURCE_REMOVE;
-}
-
-static int __aul_error_info_add_watch(int fd, aul_error_info_t *info)
-{
- GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP;
- guint source;
-
- info->io = g_io_channel_unix_new(fd);
- if (!info->io) {
- _E("Failed to create gio channel");
- return -1;
- }
-
- source = g_io_add_watch(info->io, cond, __aul_error_handler, info);
- if (!source) {
- _E("Failed to add gio watch");
- return -1;
- }
- g_io_channel_set_close_on_unref(info->io, TRUE);
-
- return 0;
-}
-
-static int __send_request_with_callback(int cmd, const char *appid, bundle *b,
- uid_t uid,
- void (*reply_cb)(bundle *b, int, void *),
- void (*error_cb)(int, void *),
- void *user_data)
-{
- aul_error_info_t *info;
- aul_reply_info_t *r_info;
- char *seq_num;
- int fd;
-
- if (!aul_is_initialized()) {
- if (aul_launch_init(NULL, NULL) < 0) {
- _E("Failed to initialize aul launch");
- return AUL_R_ENOINIT;
- }
- }
-
- if (!appid || !b || !error_cb) {
- _E("Invalid parameter");
- return AUL_R_EINVAL;
- }
-
- seq_num = __gen_seq_num();
- if (!seq_num) {
- _E("Out of memory");
- return AUL_R_ERROR;
- }
-
- bundle_del(b, AUL_K_SEQ_NUM);
- bundle_add(b, AUL_K_SEQ_NUM, seq_num);
-
- if (reply_cb) {
- r_info = __create_aul_reply_info(-1, seq_num,
- reply_cb, user_data);
- if (!r_info) {
- _E("Failed to create reply info");
- free(seq_num);
- return AUL_R_ERROR;
- }
- __push_aul_reply_info(r_info);
- }
-
- fd = app_request_to_launchpad_for_uid(cmd,
- appid, b, uid);
- if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) {
- _E("Failed to send launch request. appid(%s), result(%d)",
- appid, fd);
- if (reply_cb) {
- r_info = __pop_aul_reply_info(seq_num);
- if (r_info)
- __destroy_aul_reply_info(r_info);
- }
- free(seq_num);
- return AUL_R_ECOMM;
- }
-
- info = __create_aul_error_info(seq_num ,b, cmd,
- error_cb, user_data);
- if (!info) {
- _E("Failed to create error info");
- if (reply_cb) {
- r_info = __pop_aul_reply_info(seq_num);
- if (r_info)
- __destroy_aul_reply_info(r_info);
- }
- free(seq_num);
- return AUL_R_ERROR;
- }
-
- if (__aul_error_info_add_watch(fd, info) < 0) {
- _E("Failed to add resultcb watch");
- __destroy_aul_error_info(info);
- if (reply_cb) {
- r_info = __pop_aul_reply_info(seq_num);
- if (r_info)
- __destroy_aul_reply_info(r_info);
- }
- free(seq_num);
- close(fd);
- return AUL_R_ERROR;
- }
- free(seq_num);
-
- return AUL_R_OK;
-}
-
-API int aul_send_launch_request_for_uid(const char *appid, bundle *b, uid_t uid,
- void (*reply_cb)(bundle *, int, void *),
- void (*error_cb)(int, void *),
- void *user_data)
-{
- int ret;
-
- ret = __send_request_with_callback(APP_SEND_LAUNCH_REQUEST, appid, b,
- uid, reply_cb, error_cb, user_data);
-
- return ret;
-}
-
-static int __send_launch_request(const char *appid, bundle *b, uid_t uid)
-{
- char *seq_num;
- int fd;
-
- seq_num = __gen_seq_num();
- if (!seq_num) {
- _E("Out of memory");
- return AUL_R_ERROR;
- }
-
- bundle_del(b, AUL_K_SEQ_NUM);
- bundle_add(b, AUL_K_SEQ_NUM, seq_num);
- free(seq_num);
-
- fd = app_request_to_launchpad_for_uid(APP_SEND_LAUNCH_REQUEST_SYNC,
- appid, b, uid);
- if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) {
- _E("Failed to send launch request. appid(%s), result(%d)",
- appid, fd);
- return AUL_R_ECOMM;
- }
-
- return fd;
-}
-
-static int __recv_reply_bundle(int fd, bundle **reply_b)
-{
- app_pkt_t *pkt = NULL;
- bundle *kb;
- int ret;
-
- ret = aul_sock_recv_reply_pkt(fd, &pkt);
- if (ret != 0) {
- _E("Failed to receive the packet. result(%d)", ret);
- return AUL_R_ECOMM;
- }
-
- if (!(pkt->opt & AUL_SOCK_BUNDLE)) {
- _E("Invalid protocol");
- free(pkt);
- return AUL_R_ECOMM;
- }
-
- ret = pkt->cmd;
- if (ret < 0) {
- _E("The launch request is failed. result(%d)", ret);
- free(pkt);
- return AUL_R_ERROR;
- }
-
- kb = bundle_decode(pkt->data, pkt->len);
- if (kb == NULL) {
- _E("Out of memory");
- free(pkt);
- return AUL_R_ERROR;
- }
- free(pkt);
- *reply_b = kb;
-
- return ret;
-}
-
-API int aul_send_launch_request_sync_for_uid(const char *appid, bundle *b,
- uid_t uid, bundle **res_b)
-{
- int fd;
-
- if (!aul_is_initialized()) {
- if (aul_launch_init(NULL, NULL) < 0) {
- _E("Failed to initialize aul launch");
- return AUL_R_ENOINIT;
- }
- }
-
- if (!appid || !b || !res_b) {
- _E("Invalid parameter");
- return AUL_R_EINVAL;
- }
-
- fd = __send_launch_request(appid, b, uid);
- if (fd < 0)
- return fd;
-
- return __recv_reply_bundle(fd, res_b);
-}
-
-API int aul_send_resume_request_for_uid(const char *appid, bundle *b, uid_t uid,
- void (*error_cb)(int, void *), void *user_data)
-{
- int ret;
-
- ret = __send_request_with_callback(APP_SEND_RESUME_REQUEST, appid, b,
- uid, NULL, error_cb, user_data);
-
- return ret;
-}
--- /dev/null
+/*
+* Copyright (c) 2000 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <bundle_internal.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <uuid.h>
+
+#include <atomic>
+#include <functional>
+#include <list>
+#include <mutex>
+
+#include "app_request.h"
+#include "aul.h"
+#include "aul_api.h"
+#include "aul_error.h"
+#include "aul_sock.h"
+#include "aul_svc.h"
+#include "aul_svc_priv_key.h"
+#include "aul_util.h"
+#include "launch.h"
+
+using namespace aul::internal;
+
+namespace {
+
+using ErrCb = std::function<void(int, void*)>;
+using ReplyCb = std::function<void(bundle*, int, void*)>;
+
+class ReplyList;
+class ReplyInfo {
+ public:
+ ReplyInfo(int pid, std::string seq_num,
+ ReplyCb reply_cb, void* user_data)
+ : seq_num_(std::move(seq_num)), launched_pid_(pid),
+ reply_cb_(std::move(reply_cb)), user_data_(user_data) {}
+
+ void SetCallerCb(ErrCb cb,
+ void* caller_data) {
+ caller_cb_ = std::move(cb);
+ caller_data_ = caller_data;
+ }
+
+ void UnsetCallerCb() {
+ caller_cb_ = nullptr;
+ caller_data_ = nullptr;
+ }
+
+ int GetLaunchedPid() const {
+ return launched_pid_;
+ }
+
+ const ErrCb& GetCallerCb() const {
+ return caller_cb_;
+ }
+
+ void* GetCallerData() const {
+ return caller_data_;
+ }
+
+ private:
+ friend class ReplyList;
+
+ std::string seq_num_;
+ int launched_pid_;
+ ReplyCb reply_cb_;
+ void* user_data_;
+ ErrCb caller_cb_;
+ void* caller_data_ = nullptr;
+};
+
+class ReplyList {
+ public:
+ std::unique_ptr<ReplyInfo> FindByCallerData(void* caller_data) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ for (auto& i : list_) {
+ if (i->caller_data_ == caller_data)
+ return std::unique_ptr<ReplyInfo>(new ReplyInfo(*i));
+ }
+
+ return {};
+ }
+
+ std::unique_ptr<ReplyInfo> Pop(const std::string& seq_num) {
+ if (seq_num.empty())
+ return nullptr;
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ for (auto i = list_.begin(); i != list_.end(); ++i) {
+ if ((*i)->seq_num_ == seq_num) {
+ auto ret = std::move(*i);
+ list_.erase(i);
+ return ret;
+ }
+ }
+
+ return nullptr;
+ }
+
+ void Remove(int pid) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ for (auto i = list_.begin(); i != list_.end(); ) {
+ if ((*i)->launched_pid_ == pid) {
+ i = list_.erase(i);
+ } else {
+ ++i;
+ }
+ }
+ }
+
+ void Push(std::unique_ptr<ReplyInfo> info) {
+ if (info == nullptr)
+ return;
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ list_.push_back(std::move(info));
+ }
+
+ void UpdatePid(const std::string& seq_num, int launched_pid) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ auto* i = Find(seq_num);
+ if (i == nullptr)
+ return;
+ i->launched_pid_ = launched_pid;
+ }
+
+ bool SetCallerCb(int pid, ErrCb cb,
+ void* caller_data) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ auto* i = Find(pid);
+ if (i == nullptr)
+ return false;
+ i->SetCallerCb(std::move(cb), caller_data);
+ return true;
+ }
+
+ bool UnsetCallerCb(int pid, void* caller_data) {
+ std::unique_lock<std::mutex> lock(mutex_);
+ auto* i = Find(pid, caller_data);
+ if (i == nullptr)
+ return false;
+ i->UnsetCallerCb();
+ return true;
+ }
+
+ int InvokeReplyCb(const tizen_base::Bundle& b, bool is_cancel,
+ int launched_pid) {
+ if (launched_pid < 0) {
+ _E("Received pid(%d)", launched_pid);
+ return -1;
+ }
+
+ auto seq_num = b.GetString(AUL_K_SEQ_NUM);
+ if (seq_num.empty()) {
+ _E("Failed to get seq num");
+ return -1;
+ }
+
+ auto info = Pop(seq_num);
+ if (info == nullptr) {
+ _E("Failed to find reply info");
+ return -1;
+ }
+
+ if (info->reply_cb_ == nullptr) {
+ _E("Reply callback function is nullptr");
+ return -1;
+ }
+
+ auto fwdpid_str = b.GetString(AUL_K_FWD_CALLEE_PID);
+ if (is_cancel && !fwdpid_str.empty()) {
+ launched_pid = atoi(fwdpid_str.c_str());
+ auto new_info = std::make_unique<ReplyInfo>(launched_pid, seq_num,
+ info->reply_cb_, info->user_data_);
+ Push(std::move(new_info));
+
+ if (info->caller_cb_ != nullptr)
+ info->caller_cb_(launched_pid, info->caller_data_);
+
+ _W("Change reply info. fwd pid: %d", launched_pid);
+ return 0;
+ }
+
+ info->reply_cb_(b.GetHandle(), is_cancel ? 1 : 0, info->user_data_);
+
+ return 0;
+ }
+
+ private:
+ ReplyInfo* Find(const std::string& seq_num) {
+ for (auto& i : list_) {
+ if (i->seq_num_ == seq_num)
+ return i.get();
+ }
+
+ return nullptr;
+ }
+
+ ReplyInfo* Find(int pid) {
+ for (auto& i : list_) {
+ if (i->launched_pid_ == pid && i->caller_cb_ == nullptr)
+ return i.get();
+ }
+
+ return nullptr;
+ }
+
+ ReplyInfo* Find(int pid, void* caller_data) {
+ for (auto& i : list_) {
+ if (i->launched_pid_ == pid && i->caller_data_ == caller_data)
+ return i.get();
+ }
+
+ return nullptr;
+ }
+
+ private:
+ std::list<std::unique_ptr<ReplyInfo>> list_;
+ std::mutex mutex_;
+};
+
+ReplyList __reply_list;
+
+class ErrorInfo {
+ public:
+ ErrorInfo(std::string seq_num, tizen_base::Bundle b, int cmd,
+ ErrCb error_cb, void* user_data)
+ : seq_num_(std::move(seq_num)), b_(std::move(b)), cmd_(cmd),
+ error_cb_(std::move(error_cb)), user_data_(user_data) {
+ }
+
+ ErrorInfo(const ErrorInfo&) = delete;
+ ErrorInfo& operator = (const ErrorInfo&) = delete;
+
+ ~ErrorInfo() {
+ if (io_ != nullptr)
+ g_io_channel_unref(io_);
+ }
+
+ int AddWatch(int fd) {
+ GIOCondition cond = static_cast<GIOCondition> (G_IO_IN | G_IO_PRI |
+ G_IO_ERR | G_IO_HUP);
+ io_ = g_io_channel_unix_new(fd);
+ if (io_ == nullptr) {
+ _E("Failed to create gio channel");
+ return -1;
+ }
+
+ guint source = g_io_add_watch(io_, cond, ErrorHandlerCb, this);
+ if (source == 0) {
+ _E("Failed to add gio watch");
+ return -1;
+ }
+ g_io_channel_set_close_on_unref(io_, TRUE);
+
+ return 0;
+ }
+
+ static gboolean ErrorHandlerCb(GIOChannel* io, GIOCondition cond,
+ gpointer user_data) {
+ int fd = g_io_channel_unix_get_fd(io);
+ auto* info = reinterpret_cast<ErrorInfo*>(user_data);
+
+ if (info == nullptr) {
+ _E("Critical error!");
+ return G_SOURCE_REMOVE;
+ }
+
+ int res = aul_sock_recv_result_with_fd(fd);
+ if (res < 1) {
+ res = aul_error_convert(res);
+ if (res == AUL_R_LOCAL)
+ res = app_request_local(info->cmd_, info->b_.GetHandle());
+ } else {
+ __reply_list.UpdatePid(info->seq_num_, res);
+ }
+
+ _W("Sequence(%s), result(%d)", info->seq_num_.c_str(), res);
+
+ if (info->error_cb_ != nullptr) {
+ info->error_cb_(res, info->user_data_);
+ info->error_cb_ = nullptr;
+ }
+
+ if (res < 1)
+ __reply_list.Pop(info->seq_num_);
+
+ delete info;
+ return G_SOURCE_REMOVE;
+ }
+
+ private:
+ GIOChannel* io_ = nullptr;
+ std::string seq_num_;
+ tizen_base::Bundle b_;
+ int cmd_;
+ ErrCb error_cb_;
+ void* user_data_;
+};
+
+std::string __gen_seq_num() {
+ static std::atomic<int> num;
+ char buf[MAX_LOCAL_BUFSZ];
+
+ int n = num.fetch_add(1);
+ unsigned int seed = time(nullptr) + n;
+ snprintf(buf, sizeof(buf), "%d@%d", rand_r(&seed), n);
+
+ return buf;
+}
+
+int __get_caller_pid(const tizen_base::Bundle& b) {
+ std::string pid_str = b.GetString(AUL_K_ORG_CALLER_PID);
+ if (pid_str.empty())
+ pid_str = b.GetString(AUL_K_CALLER_PID);
+
+ if (pid_str.empty())
+ return -1;
+
+ int pid = atoi(pid_str.c_str());
+ if (pid <= 1)
+ return -1;
+
+ return pid;
+}
+
+int __launch_app_with_result(int cmd, const char* appid, bundle* kb,
+ void (*callback)(bundle*, int, void*), void* data, uid_t uid) {
+ if (!aul_is_initialized()) {
+ if (aul_launch_init(nullptr, nullptr) < 0)
+ return AUL_R_ENOINIT;
+ }
+
+ if (appid == nullptr || callback == nullptr || kb == nullptr)
+ return AUL_R_EINVAL;
+
+ std::string seq_num = __gen_seq_num();
+ bundle_del(kb, AUL_K_SEQ_NUM);
+ bundle_add(kb, AUL_K_SEQ_NUM, seq_num.c_str());
+
+ auto info = std::make_unique<ReplyInfo>(-1, seq_num, callback, data);
+ __reply_list.Push(std::move(info));
+
+ int ret = AppRequest(cmd, uid)
+ .With(kb)
+ .SetAppId(appid)
+ .Send();
+
+ if (ret > 0)
+ __reply_list.UpdatePid(seq_num, ret);
+ else
+ __reply_list.Pop(seq_num);
+
+ return ret;
+}
+
+int __set_caller_info(bundle* kb) {
+ const char* caller_pid;
+ const char* caller_uid;
+
+ caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID);
+ if (caller_pid == nullptr) {
+ _E("Failed to get caller pid");
+ return AUL_R_EINVAL;
+ }
+
+ caller_uid = bundle_get_val(kb, AUL_K_CALLER_UID);
+ if (caller_uid == nullptr) {
+ _E("Failed to get caller uid");
+ return AUL_R_EINVAL;
+ }
+
+ bundle_del(kb, AUL_K_ORG_CALLER_PID);
+ bundle_add(kb, AUL_K_ORG_CALLER_PID, caller_pid);
+ bundle_del(kb, AUL_K_ORG_CALLER_UID);
+ bundle_add(kb, AUL_K_ORG_CALLER_UID, caller_uid);
+
+ return AUL_R_OK;
+}
+
+int __recv_reply_bundle(int fd, bundle** reply_b) {
+ app_pkt_t* pkt = nullptr;
+ int ret = aul_sock_recv_reply_pkt(fd, &pkt);
+ if (ret != 0) {
+ _E("Failed to receive the packet. result(%d)", ret);
+ return AUL_R_ECOMM;
+ }
+
+ std::unique_ptr<app_pkt_t, decltype(free)*> pkt_auto(pkt, free);
+ if (!(pkt_auto->opt & AUL_SOCK_BUNDLE)) {
+ _E("Invalid protocol");
+ return AUL_R_ECOMM;
+ }
+
+ ret = pkt_auto->cmd;
+ if (ret < 0) {
+ _E("The launch request is failed. result(%d)", ret);
+ return AUL_R_ERROR;
+ }
+
+ bundle* kb = bundle_decode(pkt_auto->data, pkt_auto->len);
+ if (kb == nullptr) {
+ _E("Out of memory");
+ return AUL_R_ERROR;
+ }
+
+ *reply_b = kb;
+ return ret;
+}
+
+int __send_request_with_callback(int cmd, const char* appid, bundle* b,
+ uid_t uid,
+ void (*reply_cb)(bundle* b, int, void*),
+ void (*error_cb)(int, void*),
+ void* user_data) {
+ if (!aul_is_initialized()) {
+ if (aul_launch_init(nullptr, nullptr) < 0) {
+ _E("Failed to initialize aul launch");
+ return AUL_R_ENOINIT;
+ }
+ }
+
+ if (appid == nullptr || b == nullptr || error_cb == nullptr) {
+ _E("Invalid parameter");
+ return AUL_R_EINVAL;
+ }
+
+ std::string seq_num = __gen_seq_num();
+ bundle_del(b, AUL_K_SEQ_NUM);
+ bundle_add(b, AUL_K_SEQ_NUM, seq_num.c_str());
+
+ if (reply_cb != nullptr) {
+ auto r_info = std::make_unique<ReplyInfo>(-1, seq_num, reply_cb,
+ user_data);
+ __reply_list.Push(std::move(r_info));
+ }
+
+ int fd = AppRequest(cmd, uid)
+ .With(b)
+ .SetAppId(appid)
+ .Send();
+ if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) {
+ _E("Failed to send launch request. appid(%s), result(%d)",
+ appid, fd);
+ if (reply_cb)
+ __reply_list.Pop(seq_num);
+ return AUL_R_ECOMM;
+ }
+
+ auto error_info = std::make_unique<ErrorInfo>(seq_num,
+ tizen_base::Bundle(b, true, true), cmd, error_cb, user_data);
+ if (error_info.get() == nullptr) {
+ _E("Failed to create error info");
+ if (reply_cb != nullptr)
+ __reply_list.Pop(seq_num);
+ return AUL_R_ERROR;
+ }
+
+ if (error_info->AddWatch(fd) < 0) {
+ _E("Failed to add resultcb watch");
+ if (reply_cb != nullptr)
+ __reply_list.Pop(seq_num);
+ close(fd);
+ return AUL_R_ERROR;
+ }
+
+ error_info.release();
+ return AUL_R_OK;
+}
+
+int __send_launch_request(const std::string& appid, bundle* kb, uid_t uid) {
+ std::string seq_num = __gen_seq_num();
+ tizen_base::Bundle b(kb, false, false);
+ b.Delete(AUL_K_SEQ_NUM);
+ b.Add(AUL_K_SEQ_NUM, seq_num);
+
+ int fd = AppRequest(APP_SEND_LAUNCH_REQUEST_SYNC, uid)
+ .With(b)
+ .SetAppId(appid)
+ .Send();
+ if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) {
+ _E("Failed to send launch request. appid(%s), result(%d)",
+ appid.c_str(), fd);
+ return AUL_R_ECOMM;
+ }
+
+ return fd;
+}
+
+} // namespace
+
+extern "C" int app_result(int cmd, bundle* kb, int launched_pid) {
+ switch (cmd) {
+ case APP_RESULT:
+ __reply_list.InvokeReplyCb(tizen_base::Bundle(kb, false, false), false,
+ launched_pid);
+ break;
+ case APP_CANCEL:
+ __reply_list.InvokeReplyCb(tizen_base::Bundle(kb, false, false), true,
+ launched_pid);
+ break;
+ }
+
+ return 0;
+}
+
+extern "C" API int aul_launch_app_with_result(const char* pkgname, bundle* kb,
+ void (*cbfunc)(bundle*, int, void*), void* data) {
+ return __launch_app_with_result(APP_START_RES, pkgname, kb, cbfunc,
+ data, getuid());
+}
+
+extern "C" API int aul_launch_app_with_result_for_uid(const char* pkgname,
+ bundle* kb, void (*cbfunc)(bundle*, int, void*), void* data, uid_t uid) {
+ return __launch_app_with_result(APP_START_RES, pkgname, kb, cbfunc,
+ data, uid);
+}
+
+extern "C" void aul_set_instance_info(const char* app_id, bundle* kb) {
+ const char* component_id;
+ char buf[1024];
+ char uuid[37];
+ uuid_t u;
+
+ uuid_generate(u);
+ uuid_unparse(u, uuid);
+
+ component_id = bundle_get_val(kb, AUL_K_COMPONENT_ID);
+ if (component_id != nullptr) {
+ snprintf(buf, sizeof(buf), "%s:%s:%s",
+ uuid, app_id, component_id);
+ } else {
+ snprintf(buf, sizeof(buf), "%s:%s", uuid, app_id);
+ }
+
+ bundle_del(kb, AUL_K_INSTANCE_ID);
+ bundle_add(kb, AUL_K_INSTANCE_ID, buf);
+}
+
+extern "C" API int aul_forward_app(const char* pkgname, bundle* kb) {
+ if (pkgname == nullptr || kb == nullptr)
+ return AUL_R_EINVAL;
+
+ if (__set_caller_info(kb) < 0)
+ return AUL_R_EINVAL;
+
+ bundle_del(kb, AUL_SVC_K_CAN_BE_LEADER);
+ bundle_del(kb, AUL_SVC_K_REROUTE);
+ bundle_del(kb, AUL_SVC_K_RECYCLE);
+
+ const char* launch_mode = bundle_get_val(kb, AUL_SVC_K_LAUNCH_MODE);
+ if (launch_mode != nullptr && !strcmp(launch_mode, "group"))
+ aul_set_instance_info(pkgname, kb);
+
+ int ret;
+ tizen_base::Bundle dupb(kb, true, true);
+ if (bundle_get_val(kb, AUL_K_WAIT_RESULT) != nullptr) {
+ ret = AppRequest(APP_START_RES)
+ .With(kb)
+ .SetAppId(pkgname)
+ .Send();
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = AppRequest(APP_START)
+ .With(kb)
+ .SetAppId(pkgname)
+ .Send();
+ return ret;
+ }
+
+ bundle* outb = nullptr;
+ int pid = ret;
+ ret = aul_create_result_bundle(dupb.GetHandle(), &outb);
+ if (ret < 0)
+ return ret;
+ tizen_base::Bundle outb_auto(outb, false, true);
+
+ outb_auto.Delete(AUL_K_FWD_CALLEE_PID);
+ outb_auto.Add(AUL_K_FWD_CALLEE_PID, std::to_string(pid));
+ return aul_send_result(outb_auto.GetHandle(), 1);
+}
+
+extern "C" API int aul_create_result_bundle(bundle* inb, bundle** outb) {
+ *outb = nullptr;
+
+ if (inb == nullptr) {
+ _E("return msg create fail");
+ return AUL_R_EINVAL;
+ }
+
+ tizen_base::Bundle inb_auto(inb, false, false);
+ tizen_base::Bundle outb_auto;
+
+ if (!inb_auto.GetString(AUL_K_WAIT_RESULT).empty()) {
+ outb_auto.Add(AUL_K_SEND_RESULT, "1");
+ _D("original msg is msg with result");
+ } else {
+ _D("original msg is not msg with result");
+ }
+
+ std::string uid_str = inb_auto.GetString(AUL_K_ORG_CALLER_UID);
+ if (uid_str.empty()) {
+ uid_str = inb_auto.GetString(AUL_K_CALLER_UID);
+ if (uid_str.empty()) {
+ _E("Failed to find caller uid");
+ return AUL_R_EINVAL;
+ }
+ }
+
+ outb_auto.Add(AUL_K_ORG_CALLER_UID, uid_str);
+ std::string pid_str = inb_auto.GetString(AUL_K_ORG_CALLER_PID);
+ if (!pid_str.empty()) {
+ outb_auto.Add(AUL_K_ORG_CALLER_PID, pid_str);
+ goto end;
+ }
+
+ pid_str = inb_auto.GetString(AUL_K_CALLER_PID);
+ if (pid_str.empty()) {
+ _E("original msg does not have caller pid");
+ return AUL_R_EINVAL;
+ }
+
+ outb_auto.Add(AUL_K_CALLER_PID, pid_str);
+
+end:
+ std::string num_str = inb_auto.GetString(AUL_K_SEQ_NUM);
+ if (num_str.empty()) {
+ _E("original msg does not have seq num");
+ return AUL_R_ECANCELED;
+ }
+
+ outb_auto.Add(AUL_K_SEQ_NUM, num_str);
+ *outb = outb_auto.Detach();
+ return AUL_R_OK;
+}
+
+extern "C" int aul_send_result(bundle* kb, int is_cancel) {
+ int pid;
+ int ret;
+ int callee_pid;
+ int callee_pgid;
+ char callee_appid[256];
+
+ if (kb == nullptr)
+ return AUL_R_EINVAL;
+
+ tizen_base::Bundle b(kb, false, false);
+ if ((pid = __get_caller_pid(b)) < 0)
+ return AUL_R_EINVAL;
+
+ _D("caller pid : %d", pid);
+
+ if (b.GetString(AUL_K_SEND_RESULT).empty()) {
+ _D("original msg is not msg with result");
+ return AUL_R_OK;
+ }
+
+ callee_pid = getpid();
+ callee_pgid = getpgid(callee_pid);
+ b.Add(AUL_K_CALLEE_PID, std::to_string(callee_pgid));
+
+ ret = aul_app_get_appid_bypid(callee_pid, callee_appid,
+ sizeof(callee_appid));
+ if (ret == 0)
+ b.Add(AUL_K_CALLEE_APPID, callee_appid);
+ else
+ _W("fail(%d) to get callee appid by pid", ret);
+
+ ret = app_send_cmd_with_noreply(AUL_UTIL_PID,
+ (is_cancel == 1) ? APP_CANCEL : APP_RESULT, b.GetHandle());
+ _D("app_send_cmd_with_noreply : %d", ret);
+
+ return ret;
+}
+
+extern "C" API int aul_subapp_terminate_request_pid(int pid) {
+ if (pid <= 0)
+ return AUL_R_EINVAL;
+
+ __reply_list.Remove(pid);
+ return AppRequest(APP_TERM_REQ_BY_PID)
+ .SetAppIdAsPid(pid)
+ .Send();
+}
+
+extern "C" int aul_subapp_terminate_request(const char* instance_id, int pid) {
+ if (pid <= 0)
+ return AUL_R_EINVAL;
+
+ __reply_list.Remove(pid);
+ return aul_terminate_instance_async(instance_id, pid);
+}
+
+extern "C" API int aul_add_caller_cb(int pid, void (*caller_cb)(int, void*),
+ void* data) {
+ if (pid <= 0)
+ return AUL_R_EINVAL;
+
+ if (__reply_list.SetCallerCb(pid, caller_cb, data))
+ return AUL_R_OK;
+
+ return AUL_R_ERROR;
+}
+
+extern "C" API int aul_remove_caller_cb(int pid, void* data) {
+ if (pid <= 0)
+ return AUL_R_EINVAL;
+
+ if (__reply_list.UnsetCallerCb(pid, data))
+ return AUL_R_OK;
+
+ return AUL_R_ERROR;
+}
+
+extern "C" API int aul_invoke_caller_cb(void* data) {
+ auto info = __reply_list.FindByCallerData(data);
+ if (info == nullptr)
+ return 0;
+
+ g_idle_add_full(G_PRIORITY_DEFAULT, [](gpointer data) -> gboolean {
+ auto* info = reinterpret_cast<ReplyInfo*>(data);
+
+ if (info != nullptr && info->GetCallerCb() != nullptr)
+ info->GetCallerCb()(info->GetLaunchedPid(), info->GetCallerData());
+
+ delete info;
+ return G_SOURCE_REMOVE;
+ }, info.release(), nullptr);
+
+ return 0;
+}
+
+extern "C" API int aul_launch_app_with_result_async(const char* appid,
+ bundle* b, void (*callback)(bundle*, int, void*), void* data) {
+ return __launch_app_with_result(APP_START_RES_ASYNC, appid, b, callback,
+ data, getuid());
+}
+
+extern "C" API int aul_launch_app_with_result_async_for_uid(const char* appid,
+ bundle* b, void (*callback)(bundle*, int, void*), void* data, uid_t uid) {
+ return __launch_app_with_result(APP_START_RES_ASYNC, appid, b, callback,
+ data, uid);
+}
+
+extern "C" API int aul_send_launch_request_for_uid(const char* appid,
+ bundle* b, uid_t uid, void (*reply_cb)(bundle*, int, void*),
+ void (*error_cb)(int, void*), void* user_data) {
+ return __send_request_with_callback(APP_SEND_LAUNCH_REQUEST, appid, b,
+ uid, reply_cb, error_cb, user_data);
+}
+
+extern "C" API int aul_send_launch_request_sync_for_uid(const char* appid,
+ bundle* b, uid_t uid, bundle** res_b) {
+ if (!aul_is_initialized()) {
+ if (aul_launch_init(nullptr, nullptr) < 0) {
+ _E("Failed to initialize aul launch");
+ return AUL_R_ENOINIT;
+ }
+ }
+
+ if (appid == nullptr || b == nullptr || res_b == nullptr) {
+ _E("Invalid parameter");
+ return AUL_R_EINVAL;
+ }
+
+ int fd = __send_launch_request(appid, b, uid);
+ if (fd < 0)
+ return fd;
+
+ return __recv_reply_bundle(fd, res_b);
+}
+
+extern "C" API int aul_send_resume_request_for_uid(const char* appid,
+ bundle* b, uid_t uid, void (*error_cb)(int, void*), void* user_data) {
+ return __send_request_with_callback(APP_SEND_RESUME_REQUEST, appid, b,
+ uid, nullptr, error_cb, user_data);
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mock/glib_mock.h"
+#include "mock/mock_hook.h"
+#include "mock/test_fixture.h"
+
+extern "C" GIOChannel* g_io_channel_unix_new(gint fd) {
+ return MOCK_HOOK_P1(GlibMock, g_io_channel_unix_new, fd);
+}
+
+extern "C" guint g_io_add_watch(GIOChannel* channel, GIOCondition condition,
+ GIOFunc func, gpointer user_data) {
+ return MOCK_HOOK_P4(GlibMock, g_io_add_watch, channel, condition, func,
+ user_data);
+}
+
+extern "C" void g_io_channel_set_close_on_unref(GIOChannel* channel,
+ gboolean do_close) {
+ MOCK_HOOK_P2(GlibMock, g_io_channel_set_close_on_unref, channel, do_close);
+}
+
+extern "C" void g_io_channel_unref(GIOChannel* channel) {
+ MOCK_HOOK_P1(GlibMock, g_io_channel_unref, channel);
+}
+
+extern "C" gint g_io_channel_unix_get_fd(GIOChannel* channel) {
+ return MOCK_HOOK_P1(GlibMock, g_io_channel_unix_get_fd, channel);
+}
+
+extern "C" guint g_idle_add_full(gint priority, GSourceFunc function,
+ gpointer data, GDestroyNotify notify) {
+ return MOCK_HOOK_P4(GlibMock, g_idle_add_full, priority, function, data,
+ notify);
+}
+
+extern "C" GSource* g_io_create_watch(GIOChannel* channel,
+ GIOCondition condition) {
+ return MOCK_HOOK_P2(GlibMock, g_io_create_watch, channel, condition);
+}
+
+extern "C" void g_source_unref(GSource* source) {
+ MOCK_HOOK_P1(GlibMock, g_source_unref, source);
+}
+
+extern "C" void g_source_set_callback(GSource* source, GSourceFunc func,
+ gpointer data, GDestroyNotify notify) {
+ MOCK_HOOK_P4(GlibMock, g_source_set_callback, source, func, data, notify);
+}
+
+extern "C" void g_source_set_priority(GSource* source, gint priority) {
+ MOCK_HOOK_P2(GlibMock, g_source_set_priority, source, priority);
+}
+
+extern "C" guint g_source_attach (GSource* source, GMainContext* context) {
+ return MOCK_HOOK_P2(GlibMock, g_source_attach, source, context);
+}
+
+extern "C" GIOStatus g_io_channel_shutdown(GIOChannel* channel,
+ gboolean flush, GError** err) {
+ return MOCK_HOOK_P3(GlibMock, g_io_channel_shutdown, channel, flush, err);
+}
+
+extern "C" gboolean g_main_loop_is_running (GMainLoop *loop) {
+ return MOCK_HOOK_P1(GlibMock, g_main_loop_is_running, loop);
+}
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UNIT_TESTS_MOCK_GLIB_MOCK_H_
+#define UNIT_TESTS_MOCK_GLIB_MOCK_H_
+
+#include <gmock/gmock.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "mock/module_mock.h"
+
+class GlibMock : public virtual ModuleMock {
+ public:
+ GlibMock() {
+ using ::testing::_;
+ using ::testing::Return;
+ using ::testing::Invoke;
+
+ static int dummy;
+ GIOChannel* ch = (GIOChannel*)&dummy;
+ GSource* source = (GSource*)&dummy;
+
+ ON_CALL(*this, g_io_channel_unix_new(_))
+ .WillByDefault(Return(ch));
+ ON_CALL(*this, g_io_add_watch(_, _, _, _))
+ .WillByDefault(Return(1));
+ ON_CALL(*this, g_io_channel_unix_get_fd(_))
+ .WillByDefault(Return(1));
+ ON_CALL(*this, g_idle_add_full(_, _, _, _))
+ .WillByDefault(Invoke([&](gint priority, GSourceFunc function,
+ gpointer data, GDestroyNotify notify) -> guint {
+ function(data);
+ return 1;
+ }));
+ ON_CALL(*this, g_io_create_watch(_, _))
+ .WillByDefault(Return(source));
+ ON_CALL(*this, g_main_loop_is_running(_))
+ .WillByDefault(Return(TRUE));
+ }
+
+ MOCK_METHOD1(g_io_channel_unix_new, GIOChannel* (gint));
+ MOCK_METHOD4(g_io_add_watch, guint (GIOChannel*, GIOCondition,
+ GIOFunc, gpointer));
+ MOCK_METHOD2(g_io_channel_set_close_on_unref, void (GIOChannel*, gboolean));
+ MOCK_METHOD1(g_io_channel_unref, void (GIOChannel*));
+ MOCK_METHOD1(g_io_channel_unix_get_fd, gint (GIOChannel*));
+ MOCK_METHOD4(g_idle_add_full, guint (gint, GSourceFunc, gpointer,
+ GDestroyNotify));
+ MOCK_METHOD1(g_main_loop_is_running, gboolean (GMainLoop*));
+ MOCK_METHOD2(g_io_create_watch, GSource* (GIOChannel*, GIOCondition));
+ MOCK_METHOD1(g_source_unref, void (GSource*));
+ MOCK_METHOD4(g_source_set_callback, void (GSource*, GSourceFunc, gpointer,
+ GDestroyNotify));
+ MOCK_METHOD2(g_source_set_priority, void (GSource*, gint));
+ MOCK_METHOD2(g_source_attach, guint (GSource*, GMainContext*));
+ MOCK_METHOD3(g_io_channel_shutdown, GIOStatus (GIOChannel*, gboolean,
+ GError**));
+};
+
+#endif // UNIT_TESTS_MOCK_GLIB_MOCK_H_
#include "launch.h"
#include "mock/dbus_mock.h"
+#include "mock/glib_mock.h"
#include "mock/mock_hook.h"
#include "mock/os_mock.h"
#include "mock/socket_mock.h"
class Mocks : virtual public ::testing::NiceMock<SocketMock>,
virtual public ::testing::NiceMock<OsMock>,
+ virtual public ::testing::NiceMock<GlibMock>,
virtual public ::testing::NiceMock<DbusMock> {};
} // namespace
return std::unique_ptr<app_pkt_t, decltype(free)*>(pkt, free);
}
+
+ std::unique_ptr<app_pkt_t, decltype(free)*> MakePacket(
+ std::string str) {
+ app_pkt_t* pkt =
+ static_cast<app_pkt_t*>(calloc(1, sizeof(app_pkt_t) + str.length() + 1));
+ pkt->opt = AUL_SOCK_NONE;
+ pkt->cmd = APP_GET_INFO_OK;
+ pkt->len = str.length() + 1;
+ memcpy(pkt->data, str.c_str(), str.length());
+
+ return std::unique_ptr<app_pkt_t, decltype(free)*>(pkt, free);
+ }
};
TEST_F(LaunchWithResultTest, aul_send_resume_request_for_uid) {
cmd = header->cmd;
return n;
}));
+ EXPECT_CALL(GetMock<GlibMock>(), g_io_add_watch(_, _, _, _))
+ .WillOnce(Invoke([](GIOChannel* channel, GIOCondition condition,
+ GIOFunc func, gpointer user_data) -> guint {
+ func(channel, condition, user_data);
+ return 1;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = 100;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
int ret = aul_send_resume_request_for_uid("test_appid", b.GetHandle(),
getuid(), [](int, void*) {}, nullptr);
EXPECT_EQ(cmd, APP_TERM_REQ_BY_PID);
}
+TEST_F(LaunchWithResultTest, aul_subapp_terminate_request) {
+ int cmd = -1;
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = 0;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_subapp_terminate_request("inst", 100);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(cmd, APP_TERM_INSTANCE_ASYNC);
+}
+
TEST_F(LaunchWithResultTest, aul_create_result_bundle) {
tizen_base::Bundle inb = {
{ AUL_K_CALLER_UID, "10" },
EXPECT_EQ(ret, AUL_R_OK);
EXPECT_EQ(cmd, APP_START);
}
+
+TEST_F(LaunchWithResultTest, aul_launch_app_with_result) {
+ int cmd = -1;
+ tizen_base::Bundle b;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = 100;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_launch_app_with_result("test_appid", b.GetHandle(),
+ [](bundle*, int, void*) {}, nullptr);
+ EXPECT_EQ(ret, 100);
+ EXPECT_EQ(cmd, APP_START_RES);
+ ret = app_result(APP_RESULT, b.GetHandle(), 100);
+ EXPECT_EQ(ret, AUL_R_OK);
+}
+
+TEST_F(LaunchWithResultTest, aul_launch_app_with_result_for_uid) {
+ int cmd = -1;
+ tizen_base::Bundle b;
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = 100;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+
+ int ret = aul_launch_app_with_result_for_uid("test_appid", b.GetHandle(),
+ [](bundle*, int, void*) {}, nullptr, getuid());
+ EXPECT_EQ(ret, 100);
+ EXPECT_EQ(cmd, APP_START_RES);
+ b.Add(AUL_K_FWD_CALLEE_PID, "200");
+ ret = app_result(APP_CANCEL, b.GetHandle(), 100);
+ EXPECT_EQ(ret, AUL_R_OK);
+}
+
+TEST_F(LaunchWithResultTest, aul_set_instance_info) {
+ tizen_base::Bundle b = {
+ { AUL_K_COMPONENT_ID, "comp" }
+ };
+
+ aul_set_instance_info("test-app", b.GetHandle());
+ EXPECT_FALSE(b.GetString(AUL_K_INSTANCE_ID).empty());
+}
+
+TEST_F(LaunchWithResultTest, aul_send_result) {
+ int cmd1 = -1;
+ int cmd2 = -1;
+ tizen_base::Bundle b = {
+ { AUL_K_SEND_RESULT, "1" },
+ { AUL_K_CALLER_PID, "100" }
+ };
+ auto pkt = MakePacket("test-appid");
+
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(2)
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd1 = header->cmd;
+ return n;
+ }))
+ .WillOnce(Invoke([&](int fd, const void* buf, size_t n, int flags)
+ -> ssize_t {
+ const app_pkt_t* header = reinterpret_cast<const app_pkt_t*>(buf);
+ cmd2 = header->cmd;
+ return n;
+ }));
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(2)
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ memcpy(buf, pkt.get(), n); // Header
+ return n;
+ }))
+ .WillOnce(Invoke([&](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ memcpy(buf, pkt->data, n); // Body
+ return n;
+ }));
+
+ int ret = aul_send_result(b.GetHandle(), 0);
+ EXPECT_EQ(ret, AUL_R_OK);
+ EXPECT_EQ(cmd1, APP_GET_APPID_BYPID);
+ EXPECT_EQ(cmd2, APP_RESULT);
+}
+
+TEST_F(LaunchWithResultTest, aul_add_caller_cb) {
+ tizen_base::Bundle b;
+ constexpr const int ret_pid = 9216;
+ EXPECT_CALL(GetMock<SocketMock>(), send(_, _, _, _))
+ .Times(1);
+ EXPECT_CALL(GetMock<SocketMock>(), recv(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke([](int fd, void* buf, size_t n, int flags) -> ssize_t {
+ int ret = ret_pid;
+ memcpy(buf, &ret, sizeof(int));
+ return sizeof(int);
+ }));
+ int ret = aul_launch_app_with_result("test_appid", b.GetHandle(),
+ [](bundle*, int, void*) {}, nullptr);
+ EXPECT_EQ(ret, ret_pid);
+
+ static int dummy;
+ ret = aul_add_caller_cb(ret_pid, [](int pid, void* data) {}, &dummy);
+ EXPECT_EQ(ret, AUL_R_OK);
+ ret = aul_invoke_caller_cb(&dummy);
+ EXPECT_EQ(ret, AUL_R_OK);
+ ret = aul_remove_caller_cb(ret_pid, &dummy);
+ EXPECT_EQ(ret, AUL_R_OK);
+}
\ No newline at end of file