--- /dev/null
+/*
+* Copyright (c) 2017 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 "vc_setting_dbus.h"
+#include "vc_main.h"
+
+
+static int g_s_waiting_time = 3000;
+
+static Ecore_Fd_Handler* g_s_fd_handler = NULL;
+
+static DBusConnection* g_s_conn_sender = NULL;
+static DBusConnection* g_s_conn_listener = NULL;
+
+
+static Eina_Bool listener_setting_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
+{
+ if (NULL == g_s_conn_listener) return ECORE_CALLBACK_RENEW;
+
+ dbus_connection_read_write_dispatch(g_s_conn_listener, 50);
+
+ while (1) {
+ DBusMessage* msg = NULL;
+ msg = dbus_connection_pop_message(g_s_conn_listener);
+
+ /* loop again if we haven't read a message */
+ if (NULL == msg) {
+ break;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ char if_name[64] = {0, };
+ snprintf(if_name, 64, "%s", VC_SETTING_SERVICE_INTERFACE);
+
+ if (dbus_message_is_method_call(msg, if_name, VCD_METHOD_HELLO)) {
+ SLOG(LOG_DEBUG, TAG_VCS, "@@@ Get Hello");
+ int pid = 0;
+ int response = -1;
+
+ dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &pid, DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (pid > 0) {
+ SLOG(LOG_DEBUG, TAG_VCS, "@@ vc get hello : pid(%d) ", pid);
+ response = 1;
+ } else {
+ SLOG(LOG_ERROR, TAG_VCS, "@@ vc get hello : invalid pid ");
+ }
+
+ DBusMessage* reply = NULL;
+ reply = dbus_message_new_method_return(msg);
+
+ if (NULL != reply) {
+ dbus_message_append_args(reply, DBUS_TYPE_INT32, &response, DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send(g_s_conn_listener, reply, NULL))
+ SLOG(LOG_ERROR, TAG_VCS, "@@ vc get hello : fail to send reply");
+ else
+ SLOG(LOG_DEBUG, TAG_VCS, "@@ vc get hello : result(%d)", response);
+
+ dbus_connection_flush(g_s_conn_listener);
+ dbus_message_unref(reply);
+ } else {
+ SLOG(LOG_ERROR, TAG_VCS, "@@ vc get hello : fail to create reply message");
+ }
+
+ SLOG(LOG_DEBUG, TAG_VCS, "@@@");
+ } /* VCD_METHOD_HELLO */
+
+ else {
+ SLOG(LOG_DEBUG, TAG_VCS, "Message is NOT valid");
+ dbus_message_unref(msg);
+ break;
+ }
+
+ /* free the message */
+ dbus_message_unref(msg);
+ } /* while(1) */
+
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void __vc_setting_dbus_connection_free()
+{
+ if (NULL != g_s_conn_listener) {
+ dbus_connection_close(g_s_conn_listener);
+ dbus_connection_unref(g_s_conn_listener);
+ g_s_conn_listener = NULL;
+ }
+ if (NULL != g_s_conn_sender) {
+ dbus_connection_close(g_s_conn_sender);
+ dbus_connection_unref(g_s_conn_sender);
+ g_s_conn_sender = NULL;
+ }
+}
+
+int vc_setting_dbus_open_connection()
+{
+ if (NULL != g_s_conn_sender && NULL != g_s_conn_listener) {
+ SLOG(LOG_WARN, TAG_VCS, "already existed connection ");
+ return 0;
+ }
+
+ DBusError err;
+ int ret;
+
+ /* initialise the error value */
+ dbus_error_init(&err);
+
+ /* connect to the DBUS system bus, and check for errors */
+ g_s_conn_sender = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "Dbus Connection Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (NULL == g_s_conn_sender) {
+ SLOG(LOG_ERROR, TAG_VCS, "Fail to get dbus connection ");
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ g_s_conn_listener = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "Dbus Connection Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (NULL == g_s_conn_listener) {
+ SLOG(LOG_ERROR, TAG_VCS, "Fail to get dbus connection ");
+ __vc_setting_dbus_connection_free();
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ int pid = getpid();
+
+ char service_name[64];
+ memset(service_name, '\0', 64);
+ snprintf(service_name, 64, "%s%d", VC_SETTING_SERVICE_NAME, pid);
+
+ SLOG(LOG_DEBUG, TAG_VCS, "service name is %s", service_name);
+
+ /* register our name on the bus, and check for errors */
+ ret = dbus_bus_request_name(g_s_conn_listener, service_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "Name Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
+ SLOG(LOG_ERROR, TAG_VCS, "fail dbus_bus_request_name()");
+ __vc_setting_dbus_connection_free();
+ return -2;
+ }
+
+ if (NULL != g_s_fd_handler) {
+ SLOG(LOG_WARN, TAG_VCS, "The handler already exists.");
+ __vc_setting_dbus_connection_free();
+ return 0;
+ }
+
+ char rule[128] = {0, };
+ snprintf(rule, 128, "type='signal',interface='%s'", VC_SETTING_SERVICE_INTERFACE);
+
+ /* add a rule for which messages we want to see */
+ dbus_bus_add_match(g_s_conn_listener, rule, &err);
+ dbus_connection_flush(g_s_conn_listener);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "Match Error (%s)", err.message);
+ dbus_error_free(&err);
+ __vc_setting_dbus_connection_free();
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ int fd = 0;
+ if (1 != dbus_connection_get_unix_fd(g_s_conn_listener, &fd)) {
+ SLOG(LOG_ERROR, TAG_VCS, "fail to get fd from dbus ");
+ __vc_setting_dbus_connection_free();
+ return VC_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_VCS, "Get fd from dbus : %d", fd);
+ }
+
+ g_s_fd_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)listener_setting_event_callback, g_s_conn_listener, NULL, NULL);
+ if (NULL == g_s_fd_handler) {
+ SLOG(LOG_ERROR, TAG_VCS, "fail to get fd handler from ecore ");
+ __vc_setting_dbus_connection_free();
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ return 0;
+}
+
+int vc_setting_dbus_close_connection()
+{
+ DBusError err;
+ dbus_error_init(&err);
+
+ if (NULL != g_s_fd_handler) {
+ ecore_main_fd_handler_del(g_s_fd_handler);
+ g_s_fd_handler = NULL;
+ }
+
+ int pid = getpid();
+
+ char service_name[64];
+ memset(service_name, '\0', 64);
+ snprintf(service_name, 64, "%s%d", VC_SETTING_SERVICE_NAME, pid);
+
+ dbus_bus_release_name(g_s_conn_listener, service_name, &err);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ __vc_setting_dbus_connection_free();
+
+ return 0;
+}
+
+int vc_setting_dbus_reconnect()
+{
+ if (!g_s_conn_sender || !g_s_conn_listener) {
+ vc_setting_dbus_close_connection();
+
+ if (0 != vc_setting_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Fail to reconnect");
+ return -1;
+ }
+
+ SLOG(LOG_DEBUG, TAG_VCS, "[DBUS] Reconnect");
+ return 0;
+ }
+
+ bool sender_connected = dbus_connection_get_is_connected(g_s_conn_sender);
+ bool listener_connected = dbus_connection_get_is_connected(g_s_conn_listener);
+ SLOG(LOG_WARN, TAG_VCS, "[DBUS] Sender(%s) Listener(%s)",
+ sender_connected ? "Connected" : "Not connected", listener_connected ? "Connected" : "Not connected");
+
+ if (false == sender_connected || false == listener_connected) {
+ vc_setting_dbus_close_connection();
+
+ if (0 != vc_setting_dbus_open_connection()) {
+ SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Fail to reconnect");
+ return -1;
+ }
+
+ SLOG(LOG_DEBUG, TAG_VCS, "[DBUS] Reconnect");
+ }
+
+ return 0;
+}
+
+int vc_setting_dbus_request_hello()
+{
+ if (NULL == g_s_conn_sender) {
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ VC_SERVER_SERVICE_NAME,
+ VC_SERVER_SERVICE_OBJECT_PATH,
+ VC_SERVER_SERVICE_INTERFACE,
+ VC_METHOD_HELLO);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_VCS, "@@ Request vc hello : Fail to make message");
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage* result_msg = NULL;
+ int result = 0;
+
+ result_msg = dbus_connection_send_with_reply_and_block(g_s_conn_sender, msg, 500, &err);
+
+ if (dbus_error_is_set(&err)) {
+ dbus_error_free(&err);
+ }
+
+ dbus_message_unref(msg);
+
+ if (NULL != result_msg) {
+ dbus_message_unref(result_msg);
+ result = 0;
+ } else {
+ result = VC_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
+
+int vc_setting_dbus_request_set_language(int pid, const char* language)
+{
+ if (NULL == g_s_conn_sender) {
+ SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Dbus does not open");
+ return VC_ERROR_OPERATION_FAILED;
+ }
+
+ DBusMessage* msg;
+
+ msg = dbus_message_new_method_call(
+ VC_SERVER_SERVICE_NAME,
+ VC_SERVER_SERVICE_OBJECT_PATH,
+ VC_SERVER_SERVICE_INTERFACE,
+ VC_SETTING_METHOD_SET_LANGUAGE);
+
+ if (NULL == msg) {
+ SLOG(LOG_ERROR, TAG_VCS, "@@ vc set language : Fail to make message");
+ return VC_ERROR_OPERATION_FAILED;
+ } else {
+ SLOG(LOG_DEBUG, TAG_VCS, "@@ vc set language : pid(%d)", pid);
+ }
+
+ dbus_message_append_args(msg,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_STRING, &language,
+ DBUS_TYPE_INVALID);
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ DBusMessage* result_msg;
+ int result = VC_ERROR_OPERATION_FAILED;
+
+ result_msg = dbus_connection_send_with_reply_and_block(g_s_conn_sender, msg, g_s_waiting_time, &err);
+ dbus_message_unref(msg);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "[ERROR] Dbus Error (%s)", err.message);
+ dbus_error_free(&err);
+ }
+
+ if (NULL != result_msg) {
+ dbus_message_get_args(result_msg, &err,
+ DBUS_TYPE_INT32, &result,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_error_is_set(&err)) {
+ SLOG(LOG_ERROR, TAG_VCS, "@@ Get arguments error (%s)", err.message);
+ dbus_error_free(&err);
+ result = VC_ERROR_OPERATION_FAILED;
+ }
+ dbus_message_unref(result_msg);
+
+ SLOG(LOG_DEBUG, TAG_VCS, "@@ vcd set language : result = %d", result);
+ } else {
+ SLOG(LOG_ERROR, TAG_VCS, "@@ Result message is NULL");
+ vc_setting_dbus_reconnect();
+ result = VC_ERROR_TIMED_OUT;
+ }
+
+ return result;
+}
\ No newline at end of file