+++ /dev/null
-/*
- * Copyright (c) 2025 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 <stdio.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdbool.h>
-#include <dlfcn.h>
-#include <dirent.h>
-#include <getopt.h>
-#include <errno.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <glib-unix.h>
-
-#include <rpc-port-internal.h>
-#include <bundle_internal.h>
-#include <tizen_core.h>
-
-#include "common.h"
-#include "unified-system-service-common.h"
-
-#define COMMANDLINE_OPTION_SERVICE_PLUGIN "service-plugin"
-
-#ifdef LIB64
-#define PLUGIN_LIB_DIR "/usr/lib64/system/plugin"
-#else
-#define PLUGIN_LIB_DIR "/usr/lib/system/plugin"
-#endif
-
-#define PLUGIN_LIB_PREFIX "libunified-system-service"
-#define PLUGIN_DATA_SYMBOL_PREFIX "unified_system_service"
-#define PLUGIN_DATA_SYMBOL_POSTFIX "data"
-
-struct unified_system_service_data {
- char *service_name;
- void *service_handle;
- unified_system_service *service;
- tizen_core_task_h task;
- bool is_initialized;
-};
-
-static tizen_core_task_h g_main_task = NULL;
-static GSList *g_unified_system_service_data_list = NULL;
-
-G_LOCK_DEFINE_STATIC(unified_system_service_lock);
-
-static int unified_system_service_get_backend_service(const char *service_plugin_name,
- void **service_handle,
- unified_system_service **service)
-{
- int ret = 0;
-
- char plugin_path[PATH_MAX] = { 0, };
- int plugin_path_len = 0;
-
- char plugin_data_symbol[PATH_MAX] = { 0, };
- int plugin_data_symbol_len = 0;
-
- void *temp_service_handle = NULL;
- unified_system_service *temp_service = NULL;
-
- if (service_plugin_name == NULL || service_handle == NULL || service == NULL)
- return -EINVAL;
-
- plugin_path_len = snprintf(plugin_path, sizeof(plugin_path),
- "%s/%s-%s.so",
- PLUGIN_LIB_DIR, PLUGIN_LIB_PREFIX, service_plugin_name);
- if (plugin_path_len >= sizeof(plugin_path)) {
- _E("Plugin path is too long: length(%d)", plugin_path_len);
- return -EINVAL;
- }
-
- temp_service_handle = dlopen(plugin_path, RTLD_LAZY);
- if (temp_service_handle == NULL) {
- _E("Failed to load service plugin for %s: path(%s), %s",
- service_plugin_name, plugin_path, dlerror());
- return -EINVAL;
- }
-
- plugin_data_symbol_len = snprintf(plugin_data_symbol,
- sizeof(plugin_data_symbol), "%s_%s_%s",
- PLUGIN_DATA_SYMBOL_PREFIX, service_plugin_name,
- PLUGIN_DATA_SYMBOL_POSTFIX);
- if (plugin_data_symbol_len >= sizeof(plugin_data_symbol)) {
- _E("Plugin data symbol is too long: length(%d)", plugin_data_symbol_len);
- ret = -EINVAL;
- goto error;
- }
-
- temp_service = dlsym(temp_service_handle, plugin_data_symbol);
- if (temp_service == NULL) {
- _E("Failed to find plugin data symbol for %s: symbol(%s), %s",
- service_plugin_name, plugin_data_symbol,
- dlerror());
- ret = -EINVAL;
- goto error;
- }
-
- *service_handle = temp_service_handle;
- *service = temp_service;
-
- return 0;
-error:
- if (temp_service_handle != NULL)
- dlclose(temp_service_handle);
-
- return ret;
-}
-
-static int unified_system_service_open_and_add_plugin(char **service_plugin_names)
-{
- int ret = 0;
- size_t service_plugin_names_len = 0;
- struct unified_system_service_data *service_data = NULL;
- size_t service_data_count = 0;
-
- for (size_t i = 0; service_plugin_names[i]; ++i)
- ++service_plugin_names_len;
-
- for (size_t i = 0; i < service_plugin_names_len; ++i) {
- service_data = calloc(1, sizeof(*service_data));
- if (service_data == NULL) {
- _W("Cannot allocate memory for service plugin: %s", service_plugin_names[i]);
- continue;
- }
- service_data->service_name = strdup(service_plugin_names[i]);
- if (service_data->service_name == NULL) {
- _W("Cannot allocate memory for service name: %s", service_plugin_names[i]);
- free(service_data);
- service_data = NULL;
- continue;
- }
-
- ret = unified_system_service_get_backend_service(service_plugin_names[i],
- &(service_data->service_handle),
- &(service_data->service));
- if (ret != 0) {
- _W("Cannot get service plugin: %s", service_plugin_names[i]);
- free(service_data->service_name);
- free(service_data);
- service_data = NULL;
- continue;
- }
-
- g_unified_system_service_data_list = g_slist_prepend(g_unified_system_service_data_list,
- (gpointer)service_data);
- service_data = NULL;
- ++service_data_count;
- }
-
- if (service_data_count == 0) {
- _E("Failed to get service plugin");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void delete_unified_system_service(
- struct unified_system_service_data *unified_system_service_data,
- gpointer data)
-{
- int ret = 0;
-
- if (unified_system_service_data == NULL) {
- _E("Invallid parameter: unified_system_service_data(NULL)");
- return;
- }
-
- if (unified_system_service_data->service_handle != NULL) {
- unified_system_service_data->service = NULL;
- dlclose(unified_system_service_data->service_handle);
- unified_system_service_data->service_handle = NULL;
- }
-
- free(unified_system_service_data->service_name);
- free(unified_system_service_data);
-
- return;
-}
-
-static int unified_system_service_delete_and_close_plugin(void)
-{
- enum hal_module module;
- int ret;
-
- g_slist_foreach(g_unified_system_service_data_list,
- (GFunc)delete_unified_system_service, NULL);
-
- g_slist_free(g_unified_system_service_data_list);
- g_unified_system_service_data_list = NULL;
-
- return 0;
-}
-
-static bool unified_system_service_initialize_cb(tizen_core_source_h source, int *timeout, void *data)
-{
- struct unified_system_service_data *service_data = NULL;
- int ret = 0;
-
- /* FIXME: This is error situation, task should be terminated? */
- if (data == NULL) {
- _E("Invalid unified_system_service(NULL)");
- return false;
- }
- service_data = (struct unified_system_service_data *)data;
-
- if (service_data->is_initialized)
- return false;
-
- G_LOCK(unified_system_service_lock);
-
- /**
- * FIXME: If early_init succeed and init failed, should early_init
- * called?
- */
- if (service_data->service->early_init) {
- ret = service_data->service->early_init(NULL);
- if (ret != 0) {
- _E("Failed to early initialize %s: ret(%d)",
- service_data->service_name, ret);
- goto error;
- }
- }
-
- if (service_data->service->init) {
- ret = service_data->service->init(NULL);
- if (ret != 0) {
- _E("Failed to initialize %s: ret(%d)",
- service_data->service_name, ret);
- goto error;
- }
- }
-
- service_data->is_initialized = true;
- G_UNLOCK(unified_system_service_lock);
-
- return false;
-
-error:
- G_UNLOCK(unified_system_service_lock);
-
- return false;
-}
-
-static void unified_system_service_finalize_cb(tizen_core_source_h source, void *data)
-{
- struct unified_system_service_data *service_data = NULL;
- int ret = 0;
-
- if (data == NULL) {
- _E("Invalid unified_system_service(NULL)");
- return;
- }
- service_data = (struct unified_system_service_data *)data;
-
- G_LOCK(unified_system_service_lock);
-
- if (service_data->service->exit) {
- ret = service_data->service->exit(NULL);
- if (ret != 0) {
- _E("Cannot exit %s: ret(%d)",
- service_data->service_name, ret);
- }
- }
-
- if (service_data->service->late_exit) {
- ret = service_data->service->late_exit(NULL);
- if (ret != 0) {
- _E("Cannot late exit %s: ret(%d)",
- service_data->service_name, ret);
- }
- }
-
- service_data->is_initialized = false;
- G_UNLOCK(unified_system_service_lock);
-
- _D("Exit done.");
-}
-
-static void create_unified_system_service_task(gpointer data, gpointer user_data)
-{
- tizen_core_task_h task = NULL;
- tizen_core_h core = NULL;
- tizen_core_source_h source = NULL;
-
- struct unified_system_service_data *service_data = NULL;
- size_t *failed_count = NULL;
- int ret = 0;
-
- if (data == NULL || user_data == NULL) {
- _E("Invalid parameter: data(%p), user_data(%p)", data, user_data);
- return;
- }
-
- service_data = (struct unified_system_service_data *)data;
- failed_count = (size_t *)user_data;
-
- if (service_data->service_name == NULL) {
- _E("Service name is not initialized");
- goto error;
- }
-
- ret = tizen_core_task_create(service_data->service_name, true, &task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to create tizen_core task: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_source_create(&source);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to create tizen_core source: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_task_get_tizen_core(task, &core);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to get tizen_core core from task: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_source_set_prepare_cb(source, unified_system_service_initialize_cb, service_data);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to set prepare callback: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_source_set_finalize_cb(source, unified_system_service_finalize_cb, service_data);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to set finalize callback: ret(%d)", ret);
- goto error;
- }
-
- ret = tizen_core_add_source(core, source);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to add tizen_core source to core: ret(%d)", ret);
- goto error;
- }
-
- service_data->task = task;
-
- _D("Task created for %s", service_data->service_name);
-
- ret = tizen_core_task_run(task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to run tizen_core task for %s: ret(%d)",
- service_data->service_name, ret);
- goto error;
- }
-
- return;
-
-error:
- if (source != NULL)
- tizen_core_source_destroy(source);
-
- if (task != NULL)
- tizen_core_task_destroy(task);
-
- (*failed_count)++;
-
- return;
-}
-
-static void delete_unified_system_service_task(gpointer data, gpointer user_data)
-{
- struct unified_system_service_data *service_data = NULL;
- int ret = 0;
-
- if (data == NULL) {
- _E("Invalid parameter: data(NULL)");
- return;
- }
- service_data = (struct unified_system_service_data *)data;
-
- if (service_data->task == NULL) {
- _D("No task for %s", service_data->service_name);
- return;
- }
-
- ret = tizen_core_task_quit(service_data->task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to quit task for %s", service_data->service_name);
- return;
- }
-
- ret = tizen_core_task_destroy(service_data->task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to destroy task for %s", service_data->service_name);
- return;
- }
-
- service_data->task = NULL;
-
- _D("Task destroyed for %s", service_data->service_name);
-}
-
-static int unified_system_service_start(void)
-{
- size_t failed_count = 0;
- size_t services_len = g_slist_length(g_unified_system_service_data_list);
-
- /* Create tasks for unified-system-service and then tie them */
- g_slist_foreach(g_unified_system_service_data_list,
- (GFunc)create_unified_system_service_task,
- &failed_count);
-
- if (failed_count > 0) {
- _W("Cannot register %zu/%zu service(s)",
- failed_count, services_len);
- }
-
- if (failed_count == services_len) {
- _E("Failed to start unified system service, no task is created");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static void unified_system_service_stop(void)
-{
- g_slist_foreach(g_unified_system_service_data_list,
- delete_unified_system_service_task, NULL);
-}
-
-static gboolean handle_signal_glib(gpointer data)
-{
- int signal_number = GPOINTER_TO_INT(data);
-
- _D("Received signal(%d)", signal_number);
- if (g_main_task != NULL)
- tizen_core_task_quit(g_main_task);
-
- return G_SOURCE_REMOVE;
-}
-
-static void handle_signal_std(int signal_number)
-{
- _W("Received signal(%d)", signal_number);
- raise(SIGTERM);
-}
-
-static void attach_signal_handlers(void)
-{
- g_unix_signal_add(SIGINT, handle_signal_glib, GINT_TO_POINTER(SIGINT));
- g_unix_signal_add(SIGHUP, handle_signal_glib, GINT_TO_POINTER(SIGHUP));
- g_unix_signal_add(SIGTERM, handle_signal_glib, GINT_TO_POINTER(SIGTERM));
-
- signal(SIGQUIT, handle_signal_std);
- signal(SIGABRT, handle_signal_std);
-}
-
-static void print_usage(const char *exec_name)
-{
- _E("Usage: %s --%s <service names>\n",
- exec_name, COMMANDLINE_OPTION_SERVICE_PLUGIN);
-}
-
-static int parse_arguments(int argc, char **argv, char **service_plugin_names_str)
-{
- int opt_flag = 0;
- char *parsed_service_plugin_names = NULL;
-
- struct option options[] = {
- {
- .name = COMMANDLINE_OPTION_SERVICE_PLUGIN,
- .has_arg = required_argument,
- .flag = &opt_flag,
- .val = 1
- }, {
- .name = NULL,
- .has_arg = 0,
- .flag = NULL,
- .val = 0
- },
- };
-
- if (service_plugin_names_str == NULL) {
- _E("Invalid argument: service_plugin_names_str should not be NULL");
- return -EINVAL;
- }
-
- opt_flag = 0;
- opterr = 0;
- while (getopt_long(argc, argv, "", options, NULL) != -1) {
- switch (opt_flag) {
- case 1:
- if (parsed_service_plugin_names != NULL) {
- _E("Invalid commandline argument: <service-plugin> provided twice\n");
- return -EINVAL;
- }
- parsed_service_plugin_names = optarg;
- break;
- default:
- _E("Invalid commandline argument: %s", argv[optind - 1]);
- return -EINVAL;
- }
-
- opt_flag = 0;
- }
-
- if (parsed_service_plugin_names == NULL) {
- _E("Invalid commandline argument: <service-plugin> is not provided\n");
- return -EINVAL;
- }
-
- *service_plugin_names_str = parsed_service_plugin_names;
-
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- int ret = 0;
- char *service_plugin_names_str = NULL;
- gchar **service_plugin_names = NULL;
-
- ret = parse_arguments(argc, argv, &service_plugin_names_str);
- if (ret != 0) {
- print_usage(argv[0]);
- return ret;
- }
-
- _D("Initialize unified-system-service");
-
- tizen_core_init();
-
- ret = tizen_core_task_create("main", false, &g_main_task);
- if (ret != TIZEN_CORE_ERROR_NONE) {
- _E("Failed to create tizen_core main task: ret(%d)", ret);
- tizen_core_shutdown();
- return 1;
- }
-
- service_plugin_names = g_strsplit(service_plugin_names_str, ",", 0);
- unified_system_service_open_and_add_plugin(service_plugin_names);
- g_strfreev(service_plugin_names);
- service_plugin_names = NULL;
-
- if (g_slist_length(g_unified_system_service_data_list) == 0) {
- _W("No available service plugin, exit");
-
- tizen_core_task_destroy(g_main_task);
- tizen_core_shutdown();
-
- return 0;
- }
-
- ret = unified_system_service_start();
- if (ret != 0) {
- _E("Failed to start unified-system-service: ret(%d)", ret);
-
- unified_system_service_delete_and_close_plugin();
- tizen_core_task_destroy(g_main_task);
- tizen_core_shutdown();
-
- return 1;
- }
-
- attach_signal_handlers();
-
- tizen_core_task_run(g_main_task);
-
- /* Un-load unified-system-service plugin */
- unified_system_service_stop();
- unified_system_service_delete_and_close_plugin();
-
- tizen_core_task_destroy(g_main_task);
-
- tizen_core_shutdown();
-
- _D("Exit unified-system-service");
-
- return 0;
-}