From f5edd430a8a31bc301bce3aa998281917218e846 Mon Sep 17 00:00:00 2001 From: SukhyungKang Date: Fri, 25 Mar 2022 17:08:51 +0900 Subject: [PATCH] Revert "Refactor aul launch" This reverts commit c944eb1dce7cef345f78b96ff14a390d053ba4ea. Change-Id: Ida690998d08ecd588f45edeb871be38c16380c73 --- src/aul_launch.c | 755 +++++++++++++++++++++++++++++++++++++++++++++++++ src/aul_launch.cc | 790 ---------------------------------------------------- src/aul_worker.h | 8 - src/glib_private.cc | 38 --- src/glib_private.hh | 33 --- 5 files changed, 755 insertions(+), 869 deletions(-) create mode 100644 src/aul_launch.c delete mode 100644 src/aul_launch.cc delete mode 100644 src/glib_private.cc delete mode 100644 src/glib_private.hh diff --git a/src/aul_launch.c b/src/aul_launch.c new file mode 100644 index 0000000..beb7dc2 --- /dev/null +++ b/src/aul_launch.c @@ -0,0 +1,755 @@ +/* + * Copyright (c) 2018 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 _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aul_api.h" +#include "aul_cmd.h" +#include "aul_util.h" +#include "aul.h" +#include "aul_sock.h" +#include "launch.h" +#include "key.h" +#include "aul_watch_control_internal.h" +#include "aul_worker.h" +#include "aul_watchdog.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +typedef struct client_channel_s { + int fd; + pid_t pid; + uid_t uid; + GRecMutex mutex; +} client_channel_t; + +struct aul_request_s { + int cmd; + int clifd; + bundle *b; +}; + +typedef struct aul_request_s *aul_request_h; + +typedef void (*dispatcher)(aul_request_h req); + +typedef struct aul_handler_s { + aul_handler_fn callback; + void *user_data; +} aul_handler; + +typedef struct subapp_handler_s { + bool is_subapp; + subapp_fn callback; + void *user_data; +} subapp_handler; + +typedef struct data_control_provider_handler_s { + data_control_provider_handler_fn callback; +} data_control_provider_handler; + +typedef struct launch_context_s { + bool initialized; + aul_worker_h worker; + aul_handler aul; + subapp_handler subapp; + data_control_provider_handler dcp; + GList* clients; + GRecMutex mutex; + GMainContext *thread_default_context; +} launch_context; + +static launch_context __context; + +static void __destroy_client_channel(gpointer data) +{ + client_channel_t *channel = data; + + g_rec_mutex_lock(&channel->mutex); + g_rec_mutex_unlock(&channel->mutex); + g_rec_mutex_clear(&channel->mutex); + + free(channel); +} + +static client_channel_t *__create_client_channel(int fd, pid_t pid, uid_t uid) +{ + client_channel_t *channel; + + channel = calloc(1, sizeof(client_channel_t)); + if (!channel) { + _E("Out of memory"); + return NULL; + } + + g_rec_mutex_init(&channel->mutex); + + channel->fd = fd; + channel->pid = pid; + channel->uid = uid; + + return channel; +} + +static void __add_client_channel(client_channel_t *channel) +{ + g_rec_mutex_lock(&__context.mutex); + __context.clients = g_list_append(__context.clients, channel); + g_rec_mutex_unlock(&__context.mutex); +} + +static void __remove_client_channel(client_channel_t *channel) +{ + g_rec_mutex_lock(&__context.mutex); + __context.clients = g_list_remove(__context.clients, channel); + g_rec_mutex_unlock(&__context.mutex); +} + +static client_channel_t *__find_client_channel(int fd) +{ + client_channel_t *channel; + GList *iter; + + g_rec_mutex_lock(&__context.mutex); + iter = __context.clients; + while (iter) { + channel = iter->data; + if (channel->fd == fd) { + g_rec_mutex_unlock(&__context.mutex); + return channel; + } + + iter = g_list_next(iter); + } + g_rec_mutex_unlock(&__context.mutex); + + return NULL; +} + +static void __invoke_aul_handler(aul_type type, bundle *b) +{ + if (__context.aul.callback) + __context.aul.callback(type, b, __context.aul.user_data); +} + +static void __dispatch_app_start(aul_request_h req) +{ + const char *str; + + aul_watch_control_invoke(req->b); + __invoke_aul_handler(AUL_START, req->b); + str = bundle_get_val(req->b, AUL_K_DATA_CONTROL_TYPE); + if (str && !strcmp(str, "CORE")) { + if (__context.dcp.callback) + __context.dcp.callback(req->b, 0, NULL); + } +} + +static void __dispatch_app_resume(aul_request_h req) +{ + __invoke_aul_handler(AUL_RESUME, NULL); +} + +static void __dispatch_app_term_by_pid(aul_request_h req) +{ + __invoke_aul_handler(AUL_TERMINATE, NULL); +} + +static void __dispatch_app_term_bgapp_by_pid(aul_request_h req) +{ + __invoke_aul_handler(AUL_TERMINATE_BGAPP, NULL); +} + +static void __dispatch_app_term_req_by_pid(aul_request_h req) +{ + if (__context.subapp.is_subapp) { + if (__context.subapp.callback) + __context.subapp.callback(__context.subapp.user_data); + } else { + __invoke_aul_handler(AUL_TERMINATE, NULL); + } +} + +static void __dispatch_app_result(aul_request_h req) +{ + const char *pid_str; + int pid = -1; + + pid_str = bundle_get_val(req->b, AUL_K_CALLEE_PID); + if (pid_str) + pid = atoi(pid_str); + + app_result(req->cmd, req->b, pid); +} + +static void __dispatch_app_key_event(aul_request_h req) +{ + app_key_event(req->b); +} + +static void __dispatch_app_pause_by_pid(aul_request_h req) +{ + __invoke_aul_handler(AUL_PAUSE, req->b); +} + +static void __dispatch_app_com_message(aul_request_h req) +{ + app_com_recv(req->b); +} + +static void __dispatch_app_wake(aul_request_h req) +{ + __invoke_aul_handler(AUL_WAKE, req->b); +} + +static void __dispatch_app_suspend(aul_request_h req) +{ + __invoke_aul_handler(AUL_SUSPEND, req->b); +} + +static void __dispatch_widget_get_content(aul_request_h req) +{ + const char *widget_id; + const char *instance_id; + const char *content_info; + int fds[2] = { 0, }; + int r; + + r = aul_sock_recv_reply_sock_fd(req->clifd, &fds, 1); + if (r < 0) { + _E("Failed to receive fds"); + return; + } + + widget_id = bundle_get_val(req->b, AUL_K_WIDGET_ID); + if (!widget_id) { + _E("Failed to get widget ID"); + aul_sock_send_raw_with_fd(fds[0], -EINVAL, 0, 0, + AUL_SOCK_NOREPLY); + return; + } + + instance_id = bundle_get_val(req->b, AUL_K_WIDGET_INSTANCE_ID); + if (!instance_id) { + _E("Failed to get instance ID"); + aul_sock_send_raw_with_fd(fds[0], -EINVAL, 0, 0, + AUL_SOCK_NOREPLY); + return; + } + + __invoke_aul_handler(AUL_WIDGET_CONTENT, req->b); + + content_info = bundle_get_val(req->b, AUL_K_WIDGET_CONTENT_INFO); + if (content_info) { + r = aul_sock_send_raw_with_fd(fds[0], 0, + (unsigned char *)content_info, + strlen(content_info) + 1, AUL_SOCK_NOREPLY); + } else { + r = aul_sock_send_raw_with_fd(fds[0], -ENOENT, + NULL, 0, AUL_SOCK_NOREPLY); + } + + if (r < 0) { + _E("Failed to send content info. fd(%d), result(%d)", + fds[0], r); + } +} + +static void __dispatch_app_update_requested(aul_request_h req) +{ + __invoke_aul_handler(AUL_UPDATE_REQUESTED, req->b); +} + +static void __dispatch_app_term_inst(aul_request_h req) +{ + __invoke_aul_handler(AUL_TERMINATE_INST, req->b); +} + +static void __dispatch_app_resume_inst(aul_request_h req) +{ + __invoke_aul_handler(AUL_RESUME, req->b); +} + +static void __dispatch_app_pause_inst(aul_request_h req) +{ + __invoke_aul_handler(AUL_PAUSE, req->b); +} + +static void __dispatch_app_term_bg_inst(aul_request_h req) +{ + __invoke_aul_handler(AUL_TERMINATE_BG_INST, req->b); +} + +static void __dispatch_watchdog_enable(aul_request_h req) +{ + const char *interval_str; + unsigned int interval; + + interval_str = bundle_get_val(req->b, AUL_K_INTERVAL); + if (!interval_str) { + _E("Invalid request"); + return; + } + + interval = strtoul(interval_str, NULL, 10); + aul_watchdog_start(interval); +} + +static void __dispatch_watchdog_disable(aul_request_h req) +{ + aul_watchdog_stop(); +} + +static void __dispatch_app_connect(aul_request_h req) +{ +} + +static dispatcher __dispatcher[] = { + [APP_START] = __dispatch_app_start, + [APP_START_RES] = __dispatch_app_start, + [APP_START_ASYNC] = __dispatch_app_start, + [APP_START_RES_ASYNC] = __dispatch_app_start, + [APP_OPEN] = __dispatch_app_resume, + [APP_RESUME] = __dispatch_app_resume, + [APP_RESUME_BY_PID] = __dispatch_app_resume, + [APP_TERM_BY_PID] = __dispatch_app_term_by_pid, + [APP_TERM_BY_PID_ASYNC] = __dispatch_app_term_by_pid, + [APP_TERM_BY_PID_SYNC] = __dispatch_app_term_by_pid, + [APP_TERM_BGAPP_BY_PID] = __dispatch_app_term_bgapp_by_pid, + [APP_TERM_REQ_BY_PID] = __dispatch_app_term_req_by_pid, + [APP_RESULT] = __dispatch_app_result, + [APP_CANCEL] = __dispatch_app_result, + [APP_KEY_EVENT] = __dispatch_app_key_event, + [APP_PAUSE_BY_PID] = __dispatch_app_pause_by_pid, + [APP_COM_MESSAGE] = __dispatch_app_com_message, + [APP_WAKE] = __dispatch_app_wake, + [APP_SUSPEND] = __dispatch_app_suspend, + [WIDGET_GET_CONTENT] = __dispatch_widget_get_content, + [APP_UPDATE_REQUESTED] = __dispatch_app_update_requested, + [APP_SEND_LAUNCH_REQUEST] = __dispatch_app_start, + [APP_SEND_LAUNCH_REQUEST_SYNC] = __dispatch_app_start, + [APP_TERM_INSTANCE_ASYNC] = __dispatch_app_term_inst, + [APP_RESUME_INSTANCE] = __dispatch_app_resume_inst, + [APP_PAUSE_INSTANCE] = __dispatch_app_pause_inst, + [APP_TERM_BG_INSTANCE] = __dispatch_app_term_bg_inst, + [WATCHDOG_ENABLE] = __dispatch_watchdog_enable, + [WATCHDOG_DISABLE] = __dispatch_watchdog_disable, + [APP_CONNECT] = __dispatch_app_connect, +}; + +static void __destroy_request(struct aul_request_s *req) +{ + if (req->b) + bundle_free(req->b); + free(req); +} + +static struct aul_request_s *__create_request(int cmd, int clifd, bundle *b) +{ + struct aul_request_s *req; + + req = malloc(sizeof(struct aul_request_s)); + if (!req) { + _E("Out of memory"); + return NULL; + } + + req->cmd = cmd; + req->clifd = clifd; + req->b = b; + + return req; +} + +static int __send_result(struct aul_request_s *req, int res) +{ + client_channel_t *channel; + int ret; + + if (req->cmd != WIDGET_GET_CONTENT && req->clifd >= 0) { + channel = __find_client_channel(req->clifd); + if (!channel) { + _E("Failed to find client channel. fd(%d)", req->clifd); + return -1; + } + + g_rec_mutex_lock(&channel->mutex); + ret = aul_sock_send_result_v2(req->clifd, res, false); + g_rec_mutex_unlock(&channel->mutex); + if (ret < 0) { + _E("Failed to send result. cmd(%s:%d)", + aul_cmd_convert_to_string(req->cmd), + req->cmd); + return ret; + } + } + + return 0; +} + +static gboolean __dispatch_request(gpointer data) +{ + struct aul_request_s *req = (struct aul_request_s *)data; + int ret; + + if (!__context.initialized) { + _W("Ignore request(%d)", req->cmd); + __destroy_request(req); + return G_SOURCE_REMOVE; + } + + aul_worker_remove_anr_timer(__context.worker); + + ret = __send_result(req, 0); + if (ret < 0) { + __destroy_request(req); + return G_SOURCE_REMOVE; + } + + if (req->cmd >= APP_START && req->cmd < ARRAY_SIZE(__dispatcher) && + __dispatcher[req->cmd]) { + _W("Command(%s:%d)", + aul_cmd_convert_to_string(req->cmd), req->cmd); + __dispatcher[req->cmd](req); + } else { + _E("Command(%s:%d) is not available", + aul_cmd_convert_to_string(req->cmd), req->cmd); + } + + __destroy_request(req); + + return G_SOURCE_REMOVE; +} + +static guint __g_idle_add_full(gint priority, GSourceFunc func, gpointer data) +{ + GSource *source; + guint tag; + + source = g_idle_source_new(); + if (!source) + return 0; + + g_source_set_callback(source, (GSourceFunc)func, data, NULL); + g_source_set_priority(source, priority); + tag = g_source_attach(source, __context.thread_default_context); + g_source_unref(source); + + return tag; +} + +static void __process_app_pkt(app_pkt_t *pkt, int clifd) +{ + struct aul_request_s *req; + bundle *b = NULL; + + if (pkt->opt & AUL_SOCK_BUNDLE) { + b = bundle_decode(pkt->data, pkt->len); + if (!b) { + _E("Failed to decode the packet"); + return; + } + } + + req = __create_request(pkt->cmd, clifd, b); + if (!req) { + bundle_free(b); + return; + } + + __g_idle_add_full(G_PRIORITY_DEFAULT, __dispatch_request, req); +} + +static bool __received_event_cb(int fd, int condition, void *user_data) +{ + aul_worker_h worker = user_data; + client_channel_t *channel; + app_pkt_t *pkt; + int ret; + + channel = __find_client_channel(fd); + if (!channel) { + _E("Failed to find client channel. fd(%d)", fd); + return false; + } + + if (condition & (AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL)) { + _E("IO error occurred. condition(%d), fd(%d)", condition, fd); + __remove_client_channel(channel); + __destroy_client_channel(channel); + return false; + } + + g_rec_mutex_lock(&channel->mutex); + ret = aul_sock_recv_reply_pkt_v2(fd, &pkt, false); + g_rec_mutex_unlock(&channel->mutex); + if (ret != 0) { + _E("Failed to receive the packet. error(%d)", ret); + return true; + } + + aul_worker_add_anr_timer(worker, pkt->cmd); + __process_app_pkt(pkt, fd); + free(pkt); + + return true; +} + +static bool __connected_event_cb(int fd, int condition, void *user_data) +{ + int cond = AUL_IO_IN | AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL; + aul_worker_h worker = user_data; + client_channel_t *channel = NULL; + struct ucred cr; + int clifd; + app_pkt_t *pkt; + int ret; + + pkt = aul_sock_recv_pkt(fd, &clifd, &cr); + if (!pkt) { + _E("Failed to receive the packet"); + return true; + } + + _W("pid(%d), clifd(%d), cmd(%d)", cr.pid, clifd, pkt->cmd); + if (pkt->cmd != WIDGET_GET_CONTENT) { + if (pkt->opt & AUL_SOCK_NOREPLY) { + close(clifd); + clifd = -1; + } else { + channel = __create_client_channel(clifd, + cr.pid, cr.uid); + if (!channel) { + free(pkt); + close(clifd); + return true; + } + + __add_client_channel(channel); + } + } + + aul_worker_add_anr_timer(worker, pkt->cmd); + __process_app_pkt(pkt, clifd); + + if (pkt->cmd == WIDGET_GET_CONTENT) + clifd = -1; + + free(pkt); + + if (clifd < 0) + return true; + + ret = aul_worker_add_io_job(worker, "client", clifd, cond, + __received_event_cb, worker); + if (ret < 0) { + _E("Failed to add io job. error(%d)", ret); + __remove_client_channel(channel); + __destroy_client_channel(channel); + return true; + } + + return true; +} + +static void __finalize_context(void) +{ + if (!__context.initialized) + return; + + if (__context.worker) { + aul_worker_destroy(__context.worker); + __context.worker = NULL; + } + + if (__context.thread_default_context) { + g_main_context_unref(__context.thread_default_context); + __context.thread_default_context = NULL; + } + + g_rec_mutex_lock(&__context.mutex); + if (__context.clients) { + g_list_free_full(__context.clients, __destroy_client_channel); + __context.clients = NULL; + } + + g_rec_mutex_unlock(&__context.mutex); + g_rec_mutex_clear(&__context.mutex); + + __context.initialized = false; +} + +static int __initialize_context(void) +{ + int ret; + int fd; + + if (__context.initialized) { + _E("Already initialized"); + return AUL_R_OK; + } + + fd = aul_initialize(); + if (fd < 0) { + _E("Failed to initialize aul"); + return fd; + } + + g_rec_mutex_init(&__context.mutex); + + __context.thread_default_context = g_main_context_ref_thread_default(); + + __context.worker = aul_worker_create("aul+"); + if (!__context.worker) { + __finalize_context(); + return AUL_R_ERROR; + } + + ret = aul_worker_add_io_job(__context.worker, "server", fd, AUL_IO_IN, + __connected_event_cb, __context.worker); + if (ret < 0) { + __finalize_context(); + return ret; + } + + __context.initialized = true; + + return AUL_R_OK; +} + +API int aul_launch_init(aul_handler_fn callback, void *user_data) +{ + if (callback) { + __context.aul.callback = callback; + __context.aul.user_data = user_data; + } + + return __initialize_context(); +} + +API int aul_launch_fini(void) +{ + __finalize_context(); + return AUL_R_OK; +} + +static gboolean __app_start_cb(gpointer data) +{ + bundle *b = (bundle *)data; + struct aul_request_s req = { + .cmd = APP_START, + .clifd = 0, + .b = b + }; + + __dispatch_app_start(&req); + + if (req.b) + bundle_free(req.b); + + return G_SOURCE_REMOVE; +} + +API int aul_launch_argv_handler(int argc, char **argv) +{ + bundle *b; + + if (!aul_is_initialized()) { + _E("AUL is not initialized"); + return AUL_R_ENOINIT; + } + + b = bundle_import_from_argv(argc, argv); + if (!b) + _E("Bundle is nullptr"); + + if (!__g_idle_add_full(G_PRIORITY_HIGH, __app_start_cb, b)) { + _E("Failed to add idler"); + return AUL_R_ERROR; + } + + return AUL_R_OK; +} + +API int aul_launch_local(bundle *b) +{ + if (!aul_is_initialized()) { + _E("AUL is not initialized"); + return AUL_R_ENOINIT; + } + + if (!b) + _E("Bundle is nullptr"); + + if (!__g_idle_add_full(G_PRIORITY_DEFAULT, __app_start_cb, b)) { + _E("Failed to add idler"); + return AUL_R_ERROR; + } + + return AUL_R_OK; +} + +int aul_resume_local(void) +{ + if (!aul_is_initialized()) { + _E("AUL is not initialized"); + return AUL_R_ENOINIT; + } + + __dispatch_app_resume(NULL); + + return AUL_R_OK; +} + +API int aul_set_subapp(subapp_fn callback, void *user_data) +{ + __context.subapp.is_subapp = true; + __context.subapp.callback = callback; + __context.subapp.user_data = user_data; + + return AUL_R_OK; +} + +API int aul_is_subapp(void) +{ + return (int)__context.subapp.is_subapp; +} + +API int aul_set_data_control_provider_cb(data_control_provider_handler_fn cb) +{ + __context.dcp.callback = cb; + + return AUL_R_OK; +} + +API int aul_unset_data_control_provider_cb(void) +{ + __context.dcp.callback = NULL; + + return AUL_R_OK; +} diff --git a/src/aul_launch.cc b/src/aul_launch.cc deleted file mode 100644 index 92cb178..0000000 --- a/src/aul_launch.cc +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Copyright (c) 2018 - 2022 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 -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include "aul.h" -#include "aul_api.h" -#include "aul_cmd.h" -#include "aul_sock.h" -#include "aul_util.h" -#include "aul_watch_control_internal.h" -#include "aul_watchdog.h" -#include "aul_worker.h" -#include "key.h" -#include "launch.h" - -#include "glib_private.hh" - -namespace { -using namespace aul; - -class ClientChannel { - public: - ClientChannel(int fd, pid_t pid, uid_t uid) - : fd_(fd), pid_(pid), uid_(uid) { - } - - ~ClientChannel() { - if (fd_ > -1) - close(fd_); - } - - int GetFd() const { - return fd_; - } - - pid_t GetPid() const { - return pid_; - } - - uid_t GetUid() const { - return uid_; - } - - std::recursive_mutex& GetMutex() const { - return mutex_; - } - - private: - int fd_; - pid_t pid_; - uid_t uid_; - mutable std::recursive_mutex mutex_; -}; - -class AulRequest { - public: - AulRequest(int cmd, std::shared_ptr channel, - tizen_base::Bundle b) - : cmd_(cmd), - channel_(std::move(channel)), - b_(std::move(b)) { - } - - int GetCmd() const { - return cmd_; - } - - const std::shared_ptr& GetClientChannel() const { - return channel_; - } - - const tizen_base::Bundle& GetBundle() const { - return b_; - } - - int SendResponse(int res) { - if (channel_ == nullptr) - return 0; - - std::lock_guard lock(channel_->GetMutex()); - if (cmd_ != WIDGET_GET_CONTENT && channel_->GetFd() >= 0) - return aul_sock_send_result_v2(channel_->GetFd(), res, false); - - return 0; - } - - private: - int cmd_; - std::shared_ptr channel_; - tizen_base::Bundle b_; -}; - -class AulHandler { - public: - AulHandler(aul_handler_fn cb, void* user_data) - : cb_(cb), user_data_(user_data) { - } - - void Invoke(aul_type type, bundle* b) { - if (cb_) - cb_(type, b, user_data_); - } - - private: - aul_handler_fn cb_; - void* user_data_; -}; - -class SubAppHandler { - public: - SubAppHandler(bool is_subapp, subapp_fn cb, void* user_data) - : is_subapp_(is_subapp), cb_(cb), user_data_(user_data) { - } - - bool IsSubApp() const { - return is_subapp_; - } - - void Invoke() { - if (cb_) - cb_(user_data_); - } - - private: - bool is_subapp_; - subapp_fn cb_; - void* user_data_; -}; - -class DataControlProviderHandler { - public: - DataControlProviderHandler(data_control_provider_handler_fn cb) : cb_(cb) {} - - void Invoke(bundle* b) { - if (cb_ != nullptr) - cb_(b, 0, nullptr); - } - - private: - data_control_provider_handler_fn cb_; -}; - -class LaunchContext { - public: - using Dispatcher = std::function)>; - - LaunchContext() - : aul_handler_(nullptr), - sub_app_handler_(nullptr), - data_control_provider_handler_(nullptr) { - dispatchers_ = { - { APP_START, std::bind( - &LaunchContext::DispatchAppStart, this, std::placeholders::_1) }, - { APP_START_RES, std::bind( - &LaunchContext::DispatchAppStart, this, std::placeholders::_1) }, - { APP_START_ASYNC, std::bind( - &LaunchContext::DispatchAppStart, this, std::placeholders::_1) }, - { APP_START_RES_ASYNC, std::bind( - &LaunchContext::DispatchAppStart, this, std::placeholders::_1) }, - { APP_OPEN, std::bind( - &LaunchContext::DispatchAppResume, this, std::placeholders::_1) }, - { APP_RESUME, std::bind( - &LaunchContext::DispatchAppResume, this, std::placeholders::_1) }, - { APP_RESUME_BY_PID, std::bind( - &LaunchContext::DispatchAppResume, this, std::placeholders::_1) }, - { APP_TERM_BY_PID, std::bind( - &LaunchContext::DispatchAppTermByPid, this, std::placeholders::_1) }, - { APP_TERM_BY_PID_ASYNC, std::bind( - &LaunchContext::DispatchAppTermByPid, this, std::placeholders::_1) }, - { APP_TERM_BY_PID_SYNC, std::bind( - &LaunchContext::DispatchAppTermByPid, this, std::placeholders::_1) }, - { APP_TERM_BGAPP_BY_PID, std::bind( - &LaunchContext::DispatchAppTermBgAppByPid, this, - std::placeholders::_1) }, - { APP_TERM_REQ_BY_PID, std::bind( - &LaunchContext::DispatchAppTermReqByPid, this, - std::placeholders::_1) }, - { APP_RESULT, std::bind( - &LaunchContext::DispatchAppResult, this, std::placeholders::_1) }, - { APP_CANCEL, std::bind( - &LaunchContext::DispatchAppResult, this, std::placeholders::_1) }, - { APP_KEY_EVENT, std::bind( - &LaunchContext::DispatchAppKeyEvent, this, std::placeholders::_1) }, - { APP_PAUSE_BY_PID, std::bind( - &LaunchContext::DispatchAppPauseByPid, this, std::placeholders::_1) }, - { APP_COM_MESSAGE, std::bind( - &LaunchContext::DispatchAppComMessage, this, std::placeholders::_1) }, - { APP_WAKE, std::bind( - &LaunchContext::DispatchAppWake, this, std::placeholders::_1) }, - { APP_SUSPEND, std::bind( - &LaunchContext::DispatchAppSuspend, this, std::placeholders::_1) }, - { WIDGET_GET_CONTENT, std::bind( - &LaunchContext::DispatchWidgetGetContent, this, - std::placeholders::_1) }, - { APP_UPDATE_REQUESTED, std::bind( - &LaunchContext::DispatchAppUpdateRequested, this, - std::placeholders::_1) }, - { APP_SEND_LAUNCH_REQUEST, std::bind( - &LaunchContext::DispatchAppStart, this, std::placeholders::_1) }, - { APP_SEND_LAUNCH_REQUEST_SYNC, std::bind( - &LaunchContext::DispatchAppStart, this, std::placeholders::_1) }, - { APP_TERM_INSTANCE_ASYNC, std::bind( - &LaunchContext::DispatchAppTermInst, this, std::placeholders::_1) }, - { APP_RESUME_INSTANCE, std::bind( - &LaunchContext::DispatchAppResumeInst, this, std::placeholders::_1) }, - { APP_PAUSE_INSTANCE, std::bind( - &LaunchContext::DispatchAppPauseInst, this, std::placeholders::_1) }, - { APP_TERM_BG_INSTANCE, std::bind( - &LaunchContext::DispatchAppTermBgInst, this, std::placeholders::_1) }, - { WATCHDOG_ENABLE, std::bind( - &LaunchContext::DispatchWatchdogEnable, this, - std::placeholders::_1) }, - { WATCHDOG_DISABLE, std::bind( - &LaunchContext::DispatchWatchdogDisable, this, - std::placeholders::_1) }, - { APP_CONNECT, std::bind( - &LaunchContext::DispatchAppConnect, this, std::placeholders::_1) } - }; - } - - ~LaunchContext() { - Finalize(); - } - - int Initialize() { - if (initialized_) - return AUL_R_OK; - - int fd = aul_initialize(); - if (fd < 0) { - _E("aul_initialize() is failed. error(%d)", fd); - return fd; - } - - context_ = g_main_context_ref_thread_default(); - worker_ = aul_worker_create("aul+"); - if (worker_ == nullptr) { - Finalize(); - return AUL_R_ERROR; - } - - int ret = aul_worker_add_io_job(worker_, "server", fd, AUL_IO_IN, - ConnectedEventCb, this); - if (ret < 0) { - Finalize(); - return ret; - } - - initialized_ = true; - return AUL_R_OK; - } - - void Finalize() { - if (!initialized_) - return; - - std::lock_guard lock(mutex_); - if (worker_) { - aul_worker_destroy(worker_); - worker_ = nullptr; - } - - if (context_) { - g_main_context_unref(context_); - context_ = nullptr; - } - - clients_.clear(); - initialized_ = false; - } - - void SetAulHandler(aul_handler_fn cb, void* user_data) { - aul_handler_.reset(new AulHandler(cb, user_data)); - } - - void SetSubAppHandler(subapp_fn cb, void* user_data) { - sub_app_handler_.reset(new SubAppHandler(true, cb, user_data)); - } - - const SubAppHandler* GetSubAppHandler() const { - return sub_app_handler_.get(); - } - - void SetDataControlProviderHandler(data_control_provider_handler_fn cb) { - data_control_provider_handler_.reset(new DataControlProviderHandler(cb)); - } - - void UnsetDataControlProviderHandler() { - data_control_provider_handler_.reset(); - } - - GMainContext* GetContext() const { - return context_; - } - - std::recursive_mutex& GetMutex() const { - return mutex_; - } - - bool IsInitialized() const { - return initialized_; - } - - void AulRequestPush(std::shared_ptr request) { - std::lock_guard lock(mutex_); - queue_.push(std::move(request)); - } - - bool SetIdler() { - std::lock_guard lock(mutex_); - if (idler_ != 0) - return true; - - idler_ = GLib::IdleAddFull(G_PRIORITY_HIGH, context_, IdleCb, this); - if (idler_ == 0) - return false; - - return true; - } - - void DispatchAppStart(std::shared_ptr request) { - auto* b = request->GetBundle().GetHandle(); - aul_watch_control_invoke(b); - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_START, b); - - const char* str = bundle_get_val(b, AUL_K_DATA_CONTROL_TYPE); - if (str && !strcmp(str, "CORE")) { - if (data_control_provider_handler_.get() != nullptr) - data_control_provider_handler_->Invoke(b); - } - } - - void DispatchAppResume(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_RESUME, nullptr); - } - - private: - void DispatchAppTermByPid(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_TERMINATE, nullptr); - } - - void DispatchAppTermBgAppByPid(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_TERMINATE_BGAPP, nullptr); - } - - void DispatchAppTermReqByPid(std::shared_ptr request) { - if (sub_app_handler_.get() != nullptr && sub_app_handler_->IsSubApp()) { - sub_app_handler_->Invoke(); - } else { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_TERMINATE, nullptr); - } - } - - void DispatchAppResult(std::shared_ptr request) { - int pid = -1; - std::string pid_str = request->GetBundle().GetString(AUL_K_CALLEE_PID); - if (!pid_str.empty()) - pid = std::stoi(pid_str); - - app_result(request->GetCmd(), request->GetBundle().GetHandle(), pid); - } - - void DispatchAppKeyEvent(std::shared_ptr request) { - app_key_event(request->GetBundle().GetHandle()); - } - - void DispatchAppPauseByPid(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_PAUSE, request->GetBundle().GetHandle()); - } - - void DispatchAppComMessage(std::shared_ptr request) { - app_com_recv(request->GetBundle().GetHandle()); - } - - void DispatchAppWake(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_WAKE, request->GetBundle().GetHandle()); - } - - void DispatchAppSuspend(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_SUSPEND, request->GetBundle().GetHandle()); - } - - void DispatchWidgetGetContent(std::shared_ptr request) { - auto& client = request->GetClientChannel(); - int fds[2] = { 0, }; - int ret = aul_sock_recv_reply_sock_fd(client->GetFd(), &fds, 1); - if (ret < 0) { - _E("Failed to receive fds. error(%d)", ret); - return; - } - - auto& b = request->GetBundle(); - auto widget_id = b.GetString(AUL_K_WIDGET_ID); - if (widget_id.empty()) { - _E("Failed to get widget ID"); - aul_sock_send_raw_with_fd(fds[0], -EINVAL, 0, 0, AUL_SOCK_NOREPLY); - return; - } - - auto instance_id = b.GetString(AUL_K_WIDGET_INSTANCE_ID); - if (instance_id.empty()) { - _E("Failed to get instance ID"); - aul_sock_send_raw_with_fd(fds[0], -EINVAL, 0, 0, AUL_SOCK_NOREPLY); - return; - } - - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_WIDGET_CONTENT, b.GetHandle()); - - auto content_info = b.GetString(AUL_K_WIDGET_CONTENT_INFO); - if (content_info.empty()) { - ret = aul_sock_send_raw_with_fd(fds[0], 0, - reinterpret_cast( - const_cast(content_info.c_str())), - content_info.length() + 1, AUL_SOCK_NOREPLY); - } else { - ret = aul_sock_send_raw_with_fd(fds[0], -ENOENT, nullptr, 0, - AUL_SOCK_NOREPLY); - } - - if (ret < 0) - _E("Failed to send content info. fd(%d), result(%d)", fds[0], ret); - } - - void DispatchAppUpdateRequested(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) { - aul_handler_->Invoke(AUL_UPDATE_REQUESTED, - request->GetBundle().GetHandle()); - } - } - - void DispatchAppTermInst(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) { - aul_handler_->Invoke(AUL_TERMINATE_INST, - request->GetBundle().GetHandle()); - } - } - - void DispatchAppResumeInst(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_RESUME, request->GetBundle().GetHandle()); - } - - void DispatchAppPauseInst(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) - aul_handler_->Invoke(AUL_PAUSE, request->GetBundle().GetHandle()); - } - - void DispatchAppTermBgInst(std::shared_ptr request) { - if (aul_handler_.get() != nullptr) { - aul_handler_->Invoke(AUL_TERMINATE_BG_INST, - request->GetBundle().GetHandle()); - } - } - - void DispatchWatchdogEnable(std::shared_ptr request) { - auto interval_str = request->GetBundle().GetString(AUL_K_INTERVAL); - if (interval_str.empty()) { - _E("Invalid request"); - return; - } - - unsigned int interval = strtoul(interval_str.c_str(), nullptr, 10); - aul_watchdog_start(interval); - } - - void DispatchWatchdogDisable(std::shared_ptr request) { - aul_watchdog_stop(); - } - - void DispatchAppConnect(std::shared_ptr request) { - } - - void DispatchRequest(std::shared_ptr request) { - int cmd = request->GetCmd(); - auto found = dispatchers_.find(cmd); - if (found == dispatchers_.end()) { - _E("Command(%s:%d) is not available", - aul_cmd_convert_to_string(cmd), cmd); - return; - } - - auto dispatcher = found->second; - dispatcher(std::move(request)); - } - - void AddClientChannel(int fd, std::shared_ptr client) { - std::lock_guard lock(mutex_); - clients_[fd] = std::move(client); - } - - void RemoveClientChannel(int fd) { - std::lock_guard lock(mutex_); - auto found = clients_.find(fd); - if (found == clients_.end()) - return; - - clients_.erase(found); - } - - std::shared_ptr FindClientChannel(int fd) { - std::lock_guard lock(mutex_); - auto found = clients_.find(fd); - if (found == clients_.end()) - return nullptr; - - return found->second; - } - - std::shared_ptr AulRequestPop() { - std::lock_guard lock(mutex_); - auto request = std::move(queue_.front()); - queue_.pop(); - return request; - } - - bool AulRequestEmpty() { - std::lock_guard lock(mutex_); - return queue_.empty(); - } - - void ProcessAppPkt(app_pkt_t* pkt, std::shared_ptr channel) { - bundle* b = nullptr; - if (pkt->opt & AUL_SOCK_BUNDLE) { - b = bundle_decode(pkt->data, pkt->len); - if (b == nullptr) { - _E("Failed to decode the packet"); - return; - } - } - - auto request = std::make_shared(pkt->cmd, std::move(channel), - b ? tizen_base::Bundle(b, false, true) : tizen_base::Bundle()); - if (request == nullptr) - return; - - AulRequestPush(std::move(request)); - SetIdler(); - } - - void UnsetIdler() { - std::lock_guard lock(mutex_); - if (idler_ == 0) - return; - - auto* source = g_main_context_find_source_by_id(context_, idler_); - if (source != nullptr && !g_source_is_destroyed(source)) - g_source_destroy(source); - - idler_ = 0; - } - - static gboolean IdleCb(gpointer user_data) { - auto* launch_context = static_cast(user_data); - { - std::lock_guard lock(launch_context->GetMutex()); - if (launch_context->AulRequestEmpty()) { - launch_context->UnsetIdler(); - return G_SOURCE_REMOVE; - } - } - - aul_worker_remove_anr_timer(launch_context->worker_); - auto request = std::move(launch_context->AulRequestPop()); - int ret = request->SendResponse(0); - if (ret < 0) - return G_SOURCE_CONTINUE; - - launch_context->DispatchRequest(std::move(request)); - return G_SOURCE_CONTINUE; - } - - static bool ReceivedEventCb(int fd, int condition, void* user_data) { - auto* launch_context = static_cast(user_data); - auto client = launch_context->FindClientChannel(fd); - if (client == nullptr) { - _E("Failed to find client channel. fd(%d)", fd); - return false; - } - - if (condition & (AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL)) { - _E("I/O error occurred. condition(%d), fd(%d)", condition, fd); - launch_context->RemoveClientChannel(fd); - return false; - } - - std::lock_guard lock(launch_context->GetMutex()); - app_pkt_t* pkt; - int ret = aul_sock_recv_reply_pkt_v2(fd, &pkt, false); - if (ret != 0) { - _E("Failed to receive the packet. error(%d)", ret); - return true; - } - - aul_worker_add_anr_timer(launch_context->worker_, pkt->cmd); - launch_context->ProcessAppPkt(pkt, std::move(client)); - free(pkt); - return true; - } - - static bool ConnectedEventCb(int fd, int condition, void* user_data) { - struct ucred cred; - int clifd; - app_pkt_t* pkt = aul_sock_recv_pkt(fd, &clifd, &cred); - if (pkt == nullptr) { - _E("aul_sock_recv_pkt() is failed"); - return true; - } - - auto* launch_context = static_cast(user_data); - auto pkt_auto = std::unique_ptr( - pkt, std::free); - _W("pid(%d), clifd(%d), cmd(%d)", cred.pid, clifd, pkt->cmd); - if (pkt->cmd != WIDGET_GET_CONTENT) { - if (pkt->opt & AUL_SOCK_NOREPLY) { - close(clifd); - clifd = -1; - } - } - - auto channel = std::make_shared( - clifd, cred.pid, cred.uid); - if (channel == nullptr) { - if (clifd > 0) - close(clifd); - - return true; - } - - if (clifd > -1) - launch_context->AddClientChannel(clifd, channel); - - aul_worker_add_anr_timer(launch_context->worker_, pkt->cmd); - launch_context->ProcessAppPkt(pkt, std::move(channel)); - - if (pkt->cmd == WIDGET_GET_CONTENT) - clifd = -1; - - if (clifd < 0) - return true; - - int ret = aul_worker_add_io_job(launch_context->worker_, "client", clifd, - AUL_IO_IN | AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL, - ReceivedEventCb, launch_context); - if (ret < 0) { - _E("Failed to add I/O job. error(%d)", ret); - launch_context->RemoveClientChannel(clifd); - return true; - } - - return true; - } - - private: - bool initialized_ = false; - std::unique_ptr aul_handler_; - std::unique_ptr sub_app_handler_; - std::unique_ptr data_control_provider_handler_; - std::map dispatchers_; - std::map> clients_; - std::queue> queue_; - guint idler_ = 0; - GMainContext* context_ = nullptr; - aul_worker_h worker_ = nullptr; - mutable std::recursive_mutex mutex_; -}; - -LaunchContext launch_context; - -} // namespace - -extern "C" API int aul_launch_init(aul_handler_fn callback, void* user_data) { - if (callback != nullptr) - launch_context.SetAulHandler(callback, user_data); - - return launch_context.Initialize(); -} - -extern "C" API int aul_launch_fini(void) { - launch_context.Finalize(); - return AUL_R_OK; -} - -extern "C" API int aul_launch_argv_handler(int argc, char** argv) { - if (!launch_context.IsInitialized()) { - _E("AUL is not initialized"); - return AUL_R_ENOINIT; - } - - bundle* b = bundle_import_from_argv(argc, argv); - if (b == nullptr) - _E("bundle_import_from_argv() is failed"); - - launch_context.AulRequestPush( - std::make_shared(APP_START, nullptr, - b ? tizen_base::Bundle(b, false, true) : tizen_base::Bundle())); - if (!launch_context.SetIdler()) { - _E("Failed to add idler"); - return AUL_R_ERROR; - } - - return AUL_R_OK; -} - -extern "C" API int aul_launch_local(bundle* b) { - if (!launch_context.IsInitialized()) { - _E("AUL is not initialized"); - return AUL_R_ENOINIT; - } - - if (b == nullptr) - _E("Bundle is nullptr"); - - launch_context.AulRequestPush( - std::make_shared(APP_START, nullptr, - b ? tizen_base::Bundle(b, false, true) : tizen_base::Bundle())); - if (!launch_context.SetIdler()) { - _E("Failed to add idler"); - return AUL_R_ERROR; - } - - return AUL_R_OK; -} - -extern "C" int aul_resume_local(void) { - if (!launch_context.IsInitialized()) { - _E("AUL is not initialized"); - return AUL_R_ENOINIT; - } - - launch_context.DispatchAppResume(nullptr); - return AUL_R_OK; -} - -extern "C" API int aul_set_subapp(subapp_fn callback, void* user_data) { - launch_context.SetSubAppHandler(callback, user_data); - return AUL_R_OK; -} - -extern "C" API int aul_is_subapp(void) { - auto* sub_app_handler = launch_context.GetSubAppHandler(); - if (sub_app_handler == nullptr) - return false; - - return sub_app_handler->IsSubApp() ? 1 : 0; -} - -extern "C" API int aul_set_data_control_provider_cb( - data_control_provider_handler_fn cb) { - launch_context.SetDataControlProviderHandler(cb); - return AUL_R_OK; -} - -extern "C" API int aul_unset_data_control_provider_cb(void) { - launch_context.UnsetDataControlProviderHandler(); - return AUL_R_OK; -} diff --git a/src/aul_worker.h b/src/aul_worker.h index 0198054..c4a1c10 100644 --- a/src/aul_worker.h +++ b/src/aul_worker.h @@ -19,10 +19,6 @@ #include -#ifdef __cplusplus -extern "C" { -#endif - typedef void *aul_worker_h; typedef enum { @@ -48,8 +44,4 @@ int aul_worker_add_anr_timer(aul_worker_h handle, int cmd); int aul_worker_remove_anr_timer(aul_worker_h handle); -#ifdef __cplusplus -} -#endif - #endif /* __AUL_WORKER_H__ */ diff --git a/src/glib_private.cc b/src/glib_private.cc deleted file mode 100644 index aeb1a5a..0000000 --- a/src/glib_private.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2022 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 "glib_private.hh" - -namespace aul { - -guint GLib::IdleAdd(GMainContext* context, GSourceFunc func, gpointer data) { - return IdleAddFull(G_PRIORITY_DEFAULT, context, func, data); -} - -guint GLib::IdleAddFull(guint priority, GMainContext* context, GSourceFunc func, - gpointer data) { - auto* source = g_idle_source_new(); - if (source == nullptr) - return 0; - - g_source_set_callback(source, func, data, nullptr); - g_source_set_priority(source, priority); - guint source_id = g_source_attach(source, context); - g_source_unref(source); - return source_id; -} - -} // namespace diff --git a/src/glib_private.hh b/src/glib_private.hh deleted file mode 100644 index c4ed850..0000000 --- a/src/glib_private.hh +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2022 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 GLIB_PRIVATE_HH_ -#define GLIB_PRIVATE_HH_ - -#include - -namespace aul { - -class GLib { - public: - static guint IdleAdd(GMainContext* context, GSourceFunc func, gpointer data); - static guint IdleAddFull(guint priority, GMainContext* context, - GSourceFunc func, gpointer data); -}; - -} // namespace - -#endif // GLIB_PRIVATE_HH_ -- 2.7.4