Invoke config changed callback directly
[platform/core/uifw/voice-control.git] / common / vc_config_mgr.cpp
1 /*
2 * Copyright (c) 2011-2019 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include <dirent.h>
19 #include <dlfcn.h>
20 #include <dlog.h>
21 #include <Ecore.h>
22 #include <fcntl.h>
23 #include <glib.h>
24 #include <unistd.h>
25 #include <sys/inotify.h>
26 #include <vconf.h>
27 #include <vconf-internal-keys.h>
28 #include <buxton2.h>
29 #include <mutex>
30 #include <atomic>
31 #include <string>
32
33 #include "VoiceControlConfig.h"
34 #include "VoiceControlEngines.h"
35 #include "VoiceControlClients.h"
36
37 #include "vc_config_mgr.h"
38 #include "vc_config_parser.h"
39 #include "vc_defs.h"
40 #include "vc_main.h"
41 #include "voice_control_command.h"
42
43
44 using namespace std;
45
46 #define EVENT_SIZE  (sizeof(struct inotify_event))
47 #define BUF_LEN     (EVENT_SIZE + 16)
48
49 /* for engine directory monitoring */
50 typedef struct {
51         Ecore_Fd_Handler* dir_fd_handler;
52         int dir_fd;
53         int dir_wd;
54 } vc_engine_inotify_s;
55
56 typedef struct {
57         char* before_lang;
58         char* current_lang;
59 } language_changed_cb_parameters_s;
60
61 static const char* vc_config_tag()
62 {
63         return TAG_VCCONFIG;
64 }
65
66 static atomic<bool> g_config_mgr_initialized(false);
67
68 static VoiceControlEngines *g_VoiceControlEngines = nullptr;
69
70 static VoiceControlClients *g_VoiceControlClients = nullptr;
71
72 static VoiceControlConfig *g_VoiceControlConfig = nullptr;
73
74 static Ecore_Idler *g_engine_changed_event_idler = NULL;
75 static Ecore_Idler *g_language_changed_event_idler = NULL;
76 static Ecore_Idler *g_enabled_changed_event_idler = NULL;
77
78 static int g_lang_ref_count;
79 static Ecore_Fd_Handler* g_fd_handler_lang = NULL;
80 static int g_fd_lang = -1;
81 static int g_wd_lang = -1;
82
83 static GList* g_ino_list = nullptr;
84 static mutex g_ino_list_mutex;
85
86 static int register_engine_config_updated_event(const char* path);
87 static int unregister_engine_config_updated_event();
88 static int set_current_language(const char* language);
89
90 static Eina_Bool notify_engine_changed_event_by_idler(void *data)
91 {
92         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback by idler");
93         char *engine_appid = static_cast<char *>(data);
94         [&engine_appid]() {
95                 if (nullptr == engine_appid) {
96                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine is not specified.");
97                         return;
98                 }
99
100                 if (nullptr == g_VoiceControlClients) {
101                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
102                         return;
103                 }
104
105                 SLOG(LOG_INFO, vc_config_tag(), "[INFO] Engine ID : %s", engine_appid);
106                 auto clients = g_VoiceControlClients->getClients();
107                 for (auto &clientInfo : clients) {
108                         if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
109                                 SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
110                                 continue;
111                         }
112
113                         clientInfo.invokeEngineChangedCallback(engine_appid);
114                 }
115         }();
116
117         free(engine_appid);
118         g_engine_changed_event_idler = nullptr;
119         return EINA_FALSE;
120 }
121
122 static inline void delete_engine_changed_event_invoker()
123 {
124         if (nullptr != g_engine_changed_event_idler) {
125                 void *param = ecore_idler_del(g_engine_changed_event_idler);
126                 g_engine_changed_event_idler = nullptr;
127                 free(static_cast<char *>(param));
128         }
129 }
130
131 static void notify_engine_changed(const char *engine_appid)
132 {
133         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke engine changed callback");
134         if (nullptr == engine_appid) {
135                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
136                 return;
137         }
138
139         char *param = strdup(engine_appid);
140         if (nullptr == param) {
141                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter");
142                 return;
143         }
144
145         delete_engine_changed_event_invoker();
146         g_engine_changed_event_idler = ecore_idler_add(notify_engine_changed_event_by_idler, static_cast<void *>(param));
147 }
148
149 static inline void release_language_changed_cb_params(language_changed_cb_parameters_s *params)
150 {
151         if (nullptr == params) {
152                 return;
153         }
154
155         free(params->before_lang);
156         free(params->current_lang);
157         delete params;
158 }
159
160 static Eina_Bool notify_language_changed_event_by_idler(void *data)
161 {
162         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke language changed callback by idler");
163         language_changed_cb_parameters_s *params = static_cast<language_changed_cb_parameters_s *>(data);
164         [&params]() {
165                 if (nullptr == params) {
166                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Parameters are not specified.");
167                         return;
168                 }
169
170                 if (nullptr == g_VoiceControlClients) {
171                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
172                         return;
173                 }
174
175                 SLOG(LOG_INFO, vc_config_tag(), "[INFO] Before : %s, Current : %s", params->before_lang, params->current_lang);
176                 auto clients = g_VoiceControlClients->getClients();
177                 for (auto &clientInfo : clients) {
178                         if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
179                                 SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
180                                 continue;
181                         }
182
183                         clientInfo.invokeLanguageChangedCallback(params->before_lang, params->current_lang);
184                 }
185         }();
186
187         release_language_changed_cb_params(params);
188         g_language_changed_event_idler = nullptr;
189         return EINA_FALSE;
190 }
191
192 static inline void delete_language_changed_event_invoker()
193 {
194         if (nullptr != g_language_changed_event_idler) {
195                 void *params = ecore_idler_del(g_language_changed_event_idler);
196                 g_language_changed_event_idler = nullptr;
197                 release_language_changed_cb_params(static_cast<language_changed_cb_parameters_s *>(params));
198         }
199 }
200
201 static void notify_language_changed(const char* before_lang, const char* current_lang)
202 {
203         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke language changed callback");
204         if (nullptr == before_lang || nullptr == current_lang) {
205                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
206                 return;
207         }
208
209         auto *params = new language_changed_cb_parameters_s();
210         if (nullptr == params) {
211                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter");
212                 return;
213         }
214
215         params->before_lang = strdup(before_lang);
216         params->current_lang = strdup(current_lang);
217
218         delete_language_changed_event_invoker();
219         g_engine_changed_event_idler = ecore_idler_add(notify_language_changed_event_by_idler, static_cast<void *>(params));
220 }
221
222 static Eina_Bool notify_enabled_changed_event_by_idler(void *data)
223 {
224         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled changed callback by idler");
225         bool *enable = static_cast<bool *>(data);
226         [&enable]() {
227                 if (nullptr == enable) {
228                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Engine is not specified.");
229                         return;
230                 }
231
232                 if (nullptr == g_VoiceControlClients) {
233                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No clients exist");
234                         return;
235                 }
236
237                 SLOG(LOG_INFO, vc_config_tag(), "[INFO] Enabled : %s", *enable ? "True" : "False");
238                 auto clients = g_VoiceControlClients->getClients();
239                 for (auto &clientInfo : clients) {
240                         if (false == g_VoiceControlClients->isUidValid(clientInfo.getUid())) {
241                                 SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Skip invalid client (%u)", clientInfo.getUid());
242                                 continue;
243                         }
244
245                         clientInfo.invokeEnabledChangedCallback(*enable);
246                 }
247         }();
248
249         free(enable);
250         g_enabled_changed_event_idler = nullptr;
251         return EINA_FALSE;
252 }
253
254 static inline void delete_enabled_changed_event_invoker()
255 {
256         if (nullptr != g_enabled_changed_event_idler) {
257                 void *param = ecore_idler_del(g_enabled_changed_event_idler);
258                 g_enabled_changed_event_idler = nullptr;
259                 free(static_cast<bool *>(param));
260         }
261 }
262
263 static void notify_enabled_changed(bool enable)
264 {
265         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Invoke enabled callback");
266
267         bool *param = new bool(enable);
268         if (nullptr == param) {
269                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate the memory for parameter");
270                 return;
271         }
272
273         delete_enabled_changed_event_invoker();
274         g_engine_changed_event_idler = ecore_idler_add(notify_enabled_changed_event_by_idler, static_cast<void *>(param));
275 }
276
277 static int initialize_config_info()
278 {
279         g_VoiceControlConfig = new(nothrow) VoiceControlConfig();
280         if (nullptr == g_VoiceControlConfig) {
281                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to construct config");
282                 return VC_CONFIG_ERROR_OPERATION_FAILED;
283         }
284
285         return VC_CONFIG_ERROR_NONE;
286 }
287
288 static void finalize_config_info()
289 {
290         delete g_VoiceControlConfig;
291         g_VoiceControlConfig = nullptr;
292 }
293
294 int vc_config_convert_error_code(vc_config_error_e code)
295 {
296         if (code == VC_CONFIG_ERROR_NONE)                       return VC_CONFIG_ERROR_NONE;
297         if (code == VC_CONFIG_ERROR_OPERATION_FAILED)           return VC_ERROR_OPERATION_FAILED;
298         if (code == VC_CONFIG_ERROR_INVALID_PARAMETER)          return VC_ERROR_INVALID_PARAMETER;
299         if (code == VC_CONFIG_ERROR_ENGINE_NOT_FOUND)           return VC_ERROR_ENGINE_NOT_FOUND;
300         if (code == VC_CONFIG_ERROR_INVALID_STATE)              return VC_ERROR_INVALID_STATE;
301         if (code == VC_CONFIG_ERROR_INVALID_LANGUAGE)           return VC_ERROR_INVALID_LANGUAGE;
302         if (code == VC_CONFIG_ERROR_IO_ERROR)                   return VC_ERROR_IO_ERROR;
303         if (code == VC_CONFIG_ERROR_OUT_OF_MEMORY)              return VC_ERROR_OUT_OF_MEMORY;
304
305         return VC_CONFIG_ERROR_NONE;
306 }
307
308 static int check_and_set_default_engine_id(const char* engine_id)
309 {
310         if (NULL == engine_id) {
311                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
312                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
313         }
314
315         if (g_VoiceControlEngines->isEngineIdValid(engine_id)) {
316                 SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is valid : %s", engine_id);
317                 return VC_CONFIG_ERROR_NONE;
318         }
319
320         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getFirstEngineInfo();
321         if (nullptr == engineInfo || engineInfo->getEngineId().empty()) {
322                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid engine!!");
323                 return VC_CONFIG_ERROR_OPERATION_FAILED;
324         }
325
326         string engineId = engineInfo->getEngineId();
327         SLOG(LOG_DEBUG, vc_config_tag(), "Default engine is changed : %s", engineId.c_str());
328         if (0 != vc_parser_set_engine(engineId.c_str())) {
329                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config");
330                 return VC_CONFIG_ERROR_OPERATION_FAILED;
331         }
332         notify_engine_changed(engineId.c_str());
333         g_VoiceControlConfig->setEngineId(engineId.c_str());
334
335         return VC_CONFIG_ERROR_NONE;
336 }
337
338 static bool is_language_valid_in_engine(const char* engine_id, const char* language)
339 {
340         if (NULL == engine_id || NULL == language) {
341                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
342                 return false;
343         }
344
345         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(engine_id);
346         if (nullptr == engineInfo) {
347                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine_id);
348                 return false;
349         }
350
351         bool is_language_valid = engineInfo->isLanguageValid(language);
352         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Language(%s), is valid(%d)", language, (int)is_language_valid);
353
354         return is_language_valid;
355 }
356
357 static int get_default_language_of_engine(const char* engine_id, char** language)
358 {
359         if (NULL == engine_id || NULL == language) {
360                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
361                 return VC_ERROR_OPERATION_FAILED;
362         }
363
364         if (g_VoiceControlEngines->isEngineEmpty()) {
365                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine!!");
366                 return VC_ERROR_OPERATION_FAILED;
367         }
368
369         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(engine_id);
370         if (nullptr == engineInfo) {
371                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine_id);
372                 return VC_ERROR_INVALID_PARAMETER;
373         }
374
375         if (engineInfo->getDefaultLanguage().empty()) {
376                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] default language of engine info is NULL");
377                 return VC_CONFIG_ERROR_INVALID_LANGUAGE;
378         }
379
380         *language = strdup(engineInfo->getDefaultLanguage().c_str());
381         if (NULL == *language) {
382                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory");
383                 return VC_CONFIG_ERROR_OUT_OF_MEMORY;
384         }
385
386         SLOG(LOG_DEBUG, vc_config_tag(), "Selected language : %s", *language);
387         return VC_CONFIG_ERROR_NONE;
388 }
389
390 static void release_engines_information()
391 {
392         delete g_VoiceControlEngines;
393         g_VoiceControlEngines = nullptr;
394 }
395
396 static int load_engines_information()
397 {
398         DIR *dp = NULL;
399         struct dirent *dirp = NULL;
400
401         char filepath[512] = {'\0',};
402         int filesize;
403
404         SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Release engine and Unregister engine config");
405
406         release_engines_information();
407
408         g_VoiceControlEngines = new(nothrow) VoiceControlEngines();
409         if (g_VoiceControlEngines == nullptr) {
410                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate VoiceControlEngines");
411                 return VC_CONFIG_ERROR_OUT_OF_MEMORY;
412         }
413
414         unregister_engine_config_updated_event();
415
416         SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] default directory : %s", VC_DEFAULT_ENGINE_INFO);
417
418         /* Copy default info directory to download directory */
419         dp  = opendir(VC_DEFAULT_ENGINE_INFO);
420         if (NULL == dp) {
421                 SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] No default directory : %s", VC_DEFAULT_ENGINE_INFO);
422         } else {
423                 do {
424                         dirp = readdir(dp);
425
426                         if (NULL != dirp) {
427                                 if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
428                                         continue;
429
430                                 filesize = strlen(VC_DEFAULT_ENGINE_INFO) + strlen(dirp->d_name) + 2;
431                                 if (filesize >= 512) {
432                                         SECURE_SLOG(LOG_ERROR, vc_config_tag(), "[CONFIG ERROR] File path is too long : %s", dirp->d_name);
433                                         closedir(dp);
434                                         return VC_CONFIG_ERROR_OPERATION_FAILED;
435                                 }
436
437                                 memset(filepath, '\0', 512);
438                                 snprintf(filepath, 512, "%s/%s", VC_DEFAULT_ENGINE_INFO, dirp->d_name);
439
440                                 SECURE_SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Filepath(%s)", filepath);
441
442                                 char dest[512] = {'\0',};
443                                 snprintf(dest, 512, "%s/%s", VC_DOWNLOAD_ENGINE_INFO, dirp->d_name);
444
445                                 if (0 != access(dest, F_OK)) {
446                                         if (0 != vc_parser_copy_xml(filepath, dest)) {
447                                                 SLOG(LOG_ERROR, vc_config_tag(), "[CONFIG ERROR] Fail to copy engine info");
448                                         }
449                                 }
450                         }
451                 } while (NULL != dirp);
452
453                 closedir(dp);
454         }
455
456         /* Get engine info from default engine directory */
457         dp  = opendir(VC_DOWNLOAD_ENGINE_INFO);
458         if (NULL == dp) {
459                 SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] No downloadable directory : %s", VC_DOWNLOAD_ENGINE_INFO);
460         } else {
461                 do {
462                         dirp = readdir(dp);
463
464                         if (NULL != dirp) {
465                                 if (!strcmp(".", dirp->d_name) || !strcmp("..", dirp->d_name))
466                                         continue;
467
468                                 filesize = strlen(VC_DOWNLOAD_ENGINE_INFO) + strlen(dirp->d_name) + 2;
469                                 if (filesize >= 512) {
470                                         SECURE_SLOG(LOG_ERROR, vc_config_tag(), "[CONFIG ERROR] File path is too long : %s", dirp->d_name);
471                                         closedir(dp);
472                                         return VC_CONFIG_ERROR_OPERATION_FAILED;
473                                 }
474
475                                 memset(filepath, '\0', 512);
476                                 snprintf(filepath, 512, "%s/%s", VC_DOWNLOAD_ENGINE_INFO, dirp->d_name);
477
478                                 SECURE_SLOG(LOG_DEBUG, vc_config_tag(), "[CONFIG] Filepath(%s)", filepath);
479
480                                 try {
481                                         g_VoiceControlEngines->appendEngine(filepath);
482                                         if (0 != register_engine_config_updated_event(filepath)) {
483                                                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register engine config updated event");
484                                         }
485                                 } catch (exception &error) {
486                                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info from filepath(%s). (%s)", filepath, error.what());
487                                 }
488                         }
489                 } while (NULL != dirp);
490
491                 closedir(dp);
492         }
493
494         if (g_VoiceControlEngines->isEngineEmpty()) {
495                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] No engine");
496                 return VC_CONFIG_ERROR_OPERATION_FAILED;
497         }
498
499         return VC_CONFIG_ERROR_NONE;
500 }
501
502 static Eina_Bool engine_config_inotify_event_callback(void* data, Ecore_Fd_Handler *fd_handler)
503 {
504         SLOG(LOG_DEBUG, vc_config_tag(), "@@@ Engine config updated callback event");
505         ecore_thread_main_loop_begin();
506
507         vc_engine_inotify_s *ino = (vc_engine_inotify_s *)data;
508         int dir_fd = ino->dir_fd;
509
510         int length;
511         struct inotify_event event;
512         memset(&event, '\0', sizeof(struct inotify_event));
513
514         length = read(dir_fd, &event, sizeof(struct inotify_event));
515         if (0 > length) {
516                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty Inotify event");
517                 SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
518                 ecore_thread_main_loop_end();
519                 return ECORE_CALLBACK_DONE;
520         }
521
522         if (IN_CLOSE_WRITE == event.mask) {
523                 int ret = load_engines_information();
524                 if (0 != ret) {
525                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info when config updated");
526                 }
527
528                 g_VoiceControlEngines->printOutEngineInfo();
529                 string default_language = g_VoiceControlConfig->getCurrentLanguage();
530                 bool is_language_valid = vc_config_check_default_language_is_valid(default_language.c_str());
531                 if (false == is_language_valid) {
532                         SLOG(LOG_DEBUG, vc_config_tag(), "[ERROR] Default language is not valid");
533                         char* temp_lang = NULL;
534                         string default_engine_id = g_VoiceControlConfig->getEngineId();
535                         ret = get_default_language_of_engine(default_engine_id.c_str(), &temp_lang);
536
537                         if (0 != ret) {
538                                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get language");
539                         }
540
541                         ret = set_current_language(temp_lang);
542                         if (0 != ret) {
543                                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set language");
544                         } else {
545                                 SLOG(LOG_DEBUG, vc_config_tag(), "[DEBUG] Saved default language : lang(%s)", default_language.c_str());
546                         }
547                         if (NULL != temp_lang) {
548                                 free(temp_lang);
549                                 temp_lang = NULL;
550                         }
551                 }
552         } else {
553                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Undefined event");
554         }
555
556         SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
557
558         ecore_thread_main_loop_end();
559         return ECORE_CALLBACK_PASS_ON;
560 }
561
562 static int register_engine_config_updated_event(const char* path)
563 {
564         if (NULL == path) {
565                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Path is NULL");
566                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
567         }
568
569         /* For engine directory monitoring */
570         vc_engine_inotify_s *ino = (vc_engine_inotify_s *)calloc(1, sizeof(vc_engine_inotify_s));
571         if (NULL == ino) {
572                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to allocate memory");
573                 return VC_CONFIG_ERROR_OUT_OF_MEMORY;
574         }
575
576         ino->dir_fd = inotify_init();
577         if (ino->dir_fd < 0) {
578                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to init inotify");
579                 free(ino);
580                 ino = NULL;
581
582                 return VC_CONFIG_ERROR_OPERATION_FAILED;
583         }
584
585         ino->dir_wd = inotify_add_watch(ino->dir_fd, path, IN_CLOSE_WRITE);
586         SLOG(LOG_DEBUG, vc_config_tag(), "Add inotify watch(%s)", path);
587         if (ino->dir_wd < 0) {
588                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to add watch");
589                 free(ino);
590                 ino = NULL;
591                 return VC_CONFIG_ERROR_OPERATION_FAILED;
592         }
593
594         ino->dir_fd_handler = ecore_main_fd_handler_add(ino->dir_fd, ECORE_FD_READ, (Ecore_Fd_Cb)engine_config_inotify_event_callback, (void *)ino, NULL, NULL);
595         if (NULL == ino->dir_fd_handler) {
596                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to add fd handler");
597                 free(ino);
598                 ino = NULL;
599                 return VC_CONFIG_ERROR_OPERATION_FAILED;
600         }
601
602         /* Set non-blocking mode of file */
603         int value;
604         value = fcntl(ino->dir_fd, F_GETFL, 0);
605         value |= O_NONBLOCK;
606
607         if (0 > fcntl(ino->dir_fd, F_SETFL, value)) {
608                 SLOG(LOG_WARN, vc_config_tag(), "[WARNING] Fail to set non-block mode");
609         }
610
611         unique_lock<mutex> lock(g_ino_list_mutex);
612         g_ino_list = g_list_append(g_ino_list, ino);
613
614         return VC_CONFIG_ERROR_NONE;
615 }
616
617 static int unregister_engine_config_updated_event()
618 {
619         unique_lock<mutex> lock(g_ino_list_mutex);
620
621         /* delete all inotify variable */
622         if (0 < g_list_length(g_ino_list)) {
623                 GList *iter = NULL;
624                 iter = g_list_first(g_ino_list);
625
626                 while (NULL != iter) {
627                         vc_engine_inotify_s *tmp = static_cast<vc_engine_inotify_s *>(iter->data);
628
629                         if (NULL != tmp) {
630                                 ecore_main_fd_handler_del(tmp->dir_fd_handler);
631                                 inotify_rm_watch(tmp->dir_fd, tmp->dir_wd);
632                                 close(tmp->dir_fd);
633
634                                 free(tmp);
635                                 tmp = NULL;
636                         }
637
638                         g_ino_list = g_list_delete_link(g_ino_list, iter);
639                         iter = g_list_first(g_ino_list);
640                 }
641         }
642         return VC_CONFIG_ERROR_NONE;
643 }
644
645 static Eina_Bool language_config_inotify_event_cb(void* data, Ecore_Fd_Handler *fd_handler)
646 {
647         SLOG(LOG_DEBUG, vc_config_tag(), "@@@ Config changed callback event");
648
649         if (g_fd_lang < 0) {
650                 SLOG(LOG_WARN, vc_config_tag(), "[WARN] FD for config file is closed");
651                 SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
652                 return ECORE_CALLBACK_PASS_ON;
653         }
654
655         int length;
656         struct inotify_event event;
657         memset(&event, '\0', sizeof(struct inotify_event));
658
659         length = read(g_fd_lang, &event, sizeof(struct inotify_event));
660         if (0 > length) {
661                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Empty Inotify event");
662                 SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
663                 return ECORE_CALLBACK_PASS_ON;
664         }
665
666         if (IN_CLOSE_WRITE == event.mask) {
667                 int auto_lang = -1;
668                 char* lang = NULL;
669                 char* engine = NULL;
670                 int enabled = -1;
671
672                 if (0 != vc_parser_find_config_changed(&auto_lang, &lang, &engine, &enabled))
673                         return ECORE_CALLBACK_PASS_ON;
674
675                 if (-1 != auto_lang) {
676                         g_VoiceControlConfig->setAutoLanguageEnabled(auto_lang);
677                 }
678
679                 /* Only language changed */
680                 if (NULL != lang) {
681                         string before_lang = g_VoiceControlConfig->getCurrentLanguage();
682                         g_VoiceControlConfig->setCurrentLanguage(lang);
683
684                         /* Call all callbacks of client*/
685                         notify_language_changed(before_lang.c_str(), lang);
686
687                         free(lang);
688                         lang = NULL;
689                 }
690
691                 /* Only Engine changed */
692                 if (NULL != engine) {
693                         g_VoiceControlConfig->setEngineId(engine);
694
695                         /* Call all callbacks of client*/
696                         notify_engine_changed(engine);
697                         free(engine);
698                         engine = NULL;
699                 }
700
701                 if (-1 != enabled) {
702                         g_VoiceControlConfig->setEnabled((bool)enabled);
703
704                         /* Call all callbacks of client*/
705                         notify_enabled_changed((bool)enabled);
706                 }
707         } else {
708                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Undefined event");
709         }
710
711         SLOG(LOG_DEBUG, vc_config_tag(), "@@@");
712
713         return ECORE_CALLBACK_PASS_ON;
714 }
715
716 static int set_language_by_automatic_selection()
717 {
718         char candidate_lang[6] = {'\0', };
719         char* value = NULL;
720
721         value = vconf_get_str(VCONFKEY_LANGSET);
722         if (NULL == value) {
723                 SLOG(LOG_ERROR, vc_config_tag(), "[Config ERROR] Fail to get display language");
724                 return VC_CONFIG_ERROR_OPERATION_FAILED;
725         }
726
727         strncpy(candidate_lang, value, 5);
728         free(value);
729
730         SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Display language : %s", candidate_lang);
731
732         /* Check current language */
733         string default_language = g_VoiceControlConfig->getCurrentLanguage();
734         if (0 == default_language.compare(candidate_lang)) {
735                 SLOG(LOG_DEBUG, vc_config_tag(), "[Config] VC language(%s) is same with display language", default_language.c_str());
736                 return VC_CONFIG_ERROR_NONE;
737         }
738
739         string default_engine_id = g_VoiceControlConfig->getEngineId();
740         if (true == is_language_valid_in_engine(default_engine_id.c_str(), candidate_lang)) {
741                 /* vc default language change */
742                 string before_language = g_VoiceControlConfig->getCurrentLanguage();
743                 if (0 != vc_parser_set_language(candidate_lang)) {
744                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save default language");
745                         return VC_CONFIG_ERROR_OPERATION_FAILED;
746                 }
747                 notify_language_changed(before_language.c_str(), candidate_lang);
748                 g_VoiceControlConfig->setCurrentLanguage(candidate_lang);
749
750                 SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Default language change : before(%s) current(%s)",
751                          before_language.c_str(), candidate_lang);
752
753                 /* Call all callbacks of client*/
754                 notify_language_changed(before_language.c_str(), candidate_lang);
755         } else {
756                 /* Candidate language is not valid */
757                 char* tmp_language = NULL;
758                 if (0 != get_default_language_of_engine(default_engine_id.c_str(), &tmp_language)) {
759                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to select language");
760                         return VC_CONFIG_ERROR_OPERATION_FAILED;
761                 }
762
763                 if (NULL == tmp_language) {
764                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Selected language is NULL");
765                         return VC_CONFIG_ERROR_OPERATION_FAILED;
766                 }
767
768                 string before_language = g_VoiceControlConfig->getCurrentLanguage();
769                 if (0 != vc_parser_set_language(tmp_language)) {
770                         free(tmp_language);
771                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config");
772                         return VC_CONFIG_ERROR_OPERATION_FAILED;
773                 }
774                 notify_language_changed(before_language.c_str(), tmp_language);
775                 g_VoiceControlConfig->setCurrentLanguage(tmp_language);
776
777                 SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Default language change : before(%s) current(%s)",
778                          before_language.c_str(), tmp_language);
779
780                 /* Call all callbacks of client*/
781                 notify_language_changed(before_language.c_str(), tmp_language);
782                 free(tmp_language);
783         }
784
785         return VC_CONFIG_ERROR_NONE;
786 }
787
788 static void language_changed_cb(keynode_t *key, void *data)
789 {
790         if (g_VoiceControlConfig->isAutoLanguageEnabled()) {
791                 /* Get voice input vconf key */
792                 set_language_by_automatic_selection();
793         }
794 }
795
796 static int initialize_vc_config_mgr()
797 {
798         if (g_config_mgr_initialized.load()) {
799                 SLOG(LOG_DEBUG, vc_config_tag(), "Config mgr module is already initialized");
800                 return VC_CONFIG_ERROR_NONE;
801         }
802
803         /* Get file name from default engine directory */
804         if (0 != access(VC_CONFIG_BASE, F_OK)) {
805                 if (0 != mkdir(VC_CONFIG_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
806                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_CONFIG_BASE);
807                         return VC_CONFIG_ERROR_OPERATION_FAILED;
808                 } else {
809                         SLOG(LOG_DEBUG, vc_config_tag(), "Success to make directory : %s", VC_CONFIG_BASE);
810                 }
811         }
812         if (0 != access(VC_RUNTIME_INFO_ROOT, F_OK)) {
813                 if (0 != mkdir(VC_RUNTIME_INFO_ROOT, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
814                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_RUNTIME_INFO_ROOT);
815                         return VC_CONFIG_ERROR_OPERATION_FAILED;
816                 } else {
817                         SLOG(LOG_DEBUG, vc_config_tag(), "Success to make directory : %s", VC_RUNTIME_INFO_ROOT);
818                 }
819         }
820
821         if (0 != access(VC_DOWNLOAD_BASE, F_OK)) {
822                 if (0 != mkdir(VC_DOWNLOAD_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
823                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_DOWNLOAD_BASE);
824                         return VC_CONFIG_ERROR_OPERATION_FAILED;
825                 } else {
826                         SLOG(LOG_DEBUG, vc_config_tag(), "Success to make directory : %s", VC_DOWNLOAD_BASE);
827                 }
828         }
829         if (0 != access(VC_DOWNLOAD_ENGINE_INFO, F_OK)) {
830                 if (0 != mkdir(VC_DOWNLOAD_ENGINE_INFO, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
831                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to make directory : %s", VC_DOWNLOAD_ENGINE_INFO);
832                         return VC_CONFIG_ERROR_OPERATION_FAILED;
833                 } else {
834                         SLOG(LOG_DEBUG, vc_config_tag(), "Success to make directory : %s", VC_DOWNLOAD_ENGINE_INFO);
835                 }
836         }
837
838         if (0 != load_engines_information()) {
839                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get engine info");
840                 release_engines_information();
841                 return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
842         }
843
844         g_VoiceControlEngines->printOutEngineInfo();
845
846         if (0 != initialize_config_info()) {
847                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to parse configure information");
848                 release_engines_information();
849                 return VC_CONFIG_ERROR_OPERATION_FAILED;
850         }
851
852         string default_engine_id = g_VoiceControlConfig->getEngineId();
853         if (0 != check_and_set_default_engine_id(default_engine_id.c_str())) {
854                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set default engine");
855                 release_engines_information();
856                 finalize_config_info();
857                 return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
858         }
859
860         if (g_VoiceControlConfig->isAutoLanguageEnabled()) {
861                 /* Check language with display language */
862                 set_language_by_automatic_selection();
863         } else {
864                 string default_language = g_VoiceControlConfig->getCurrentLanguage();
865                 if (false == is_language_valid_in_engine(default_engine_id.c_str(), default_language.c_str())) {
866                         /* Default language is not valid */
867                         char* tmp_language;
868                         if (0 != get_default_language_of_engine(default_engine_id.c_str(), &tmp_language)) {
869                                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to select language");
870                                 release_engines_information();
871                                 finalize_config_info();
872                                 return VC_CONFIG_ERROR_OPERATION_FAILED;
873                         }
874
875                         if (NULL != tmp_language) {
876                                 g_VoiceControlConfig->setCurrentLanguage(tmp_language);
877                                 if (0 != vc_parser_set_language(tmp_language)) {
878                                         free(tmp_language);
879                                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save config");
880                                         release_engines_information();
881                                         finalize_config_info();
882                                         return VC_CONFIG_ERROR_OPERATION_FAILED;
883                                 }
884
885                                 free(tmp_language);
886                         }
887                 }
888         }
889
890         /* print daemon config */
891         SLOG(LOG_DEBUG, vc_config_tag(), "@ Daemon config @");
892         g_VoiceControlConfig->printOutConfig();
893         SLOG(LOG_DEBUG, vc_config_tag(), "@@@@");
894
895         g_lang_ref_count = 0;
896
897         /* Register to detect display language change */
898         vconf_notify_key_changed(VCONFKEY_LANGSET, language_changed_cb, nullptr);
899
900         g_config_mgr_initialized = true;
901         return VC_CONFIG_ERROR_NONE;
902 }
903
904 int vc_config_mgr_initialize(unsigned int uid)
905 {
906         SLOG(LOG_INFO, vc_config_tag(), "[WARNING] Enter critical section");
907         ecore_thread_main_loop_begin();
908
909         int ret = initialize_vc_config_mgr();
910         if (VC_CONFIG_ERROR_NONE != ret) {
911                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to initialize vc_config_mgr");
912                 ecore_thread_main_loop_end();
913                 SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
914                 return ret;
915         }
916
917         if (g_VoiceControlClients == nullptr) {
918                 g_VoiceControlClients = new VoiceControlClients();
919         }
920
921         /* Check uid */
922         if (g_VoiceControlClients->isUidValid(uid)) {
923                 SLOG(LOG_WARN, vc_config_tag(), "[CONFIG] uid(%u) has already registered", uid);
924                 ecore_thread_main_loop_end();
925                 SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
926                 return VC_CONFIG_ERROR_NONE;
927         }
928
929         VoiceControlClientInfo clientInfo(uid);
930         g_VoiceControlClients->appendClient(clientInfo);
931
932         SLOG(LOG_INFO, vc_config_tag(), "[CONFIG] Add new client. uid(%u)", uid);
933
934         g_VoiceControlClients->printOutClients();
935
936         ecore_thread_main_loop_end();
937         SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
938         return VC_CONFIG_ERROR_NONE;
939 }
940
941 int vc_config_mgr_finalize(unsigned int uid)
942 {
943         SLOG(LOG_INFO, vc_config_tag(), "[WARNING] Enter critical section");
944
945         if (0 < g_VoiceControlClients->removeClient(uid)) {
946                 SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
947                 return VC_CONFIG_ERROR_NONE;
948         }
949
950         delete g_VoiceControlClients;
951         g_VoiceControlClients = nullptr;
952
953         release_engines_information();
954
955         unregister_engine_config_updated_event();
956
957         vconf_ignore_key_changed(VCONFKEY_LANGSET, language_changed_cb);
958         finalize_config_info();
959
960         SLOG(LOG_DEBUG, vc_config_tag(), "[WARNING] Leave critical section");
961
962         g_config_mgr_initialized = false;
963         SLOG(LOG_DEBUG, vc_config_tag(), "[Success] Finalize config");
964         return VC_CONFIG_ERROR_NONE;
965 }
966
967
968 static int register_language_config_changed_event()
969 {
970         if (0 == g_lang_ref_count) {
971                 /* get file notification handler */
972                 int fd;
973                 int wd;
974
975                 fd = inotify_init();
976                 if (fd < 0) {
977                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail get inotify fd");
978                         return VC_CONFIG_ERROR_OPERATION_FAILED;
979                 }
980                 g_fd_lang = fd;
981
982                 wd = inotify_add_watch(fd, VC_CONFIG, IN_CLOSE_WRITE);
983                 g_wd_lang = wd;
984
985                 g_fd_handler_lang = ecore_main_fd_handler_add(fd, ECORE_FD_READ, (Ecore_Fd_Cb)language_config_inotify_event_cb, NULL, NULL, NULL);
986                 if (NULL == g_fd_handler_lang) {
987                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get handler_noti");
988                         return VC_CONFIG_ERROR_OPERATION_FAILED;
989                 }
990
991                 /* Set non-blocking mode of file */
992                 int value;
993                 value = fcntl(fd, F_GETFL, 0);
994                 value |= O_NONBLOCK;
995
996                 if (0 > fcntl(fd, F_SETFL, value)) {
997                         SLOG(LOG_WARN, vc_config_tag(), "[WARNING] Fail to set non-block mode");
998                 }
999         }
1000         g_lang_ref_count++;
1001
1002         return VC_CONFIG_ERROR_NONE;
1003 }
1004
1005 static int unregister_language_config_event()
1006 {
1007         if (0 == g_lang_ref_count) {
1008                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Lang ref count is 0");
1009                 return VC_CONFIG_ERROR_INVALID_STATE;
1010         }
1011
1012         g_lang_ref_count--;
1013         if (0 == g_lang_ref_count) {
1014                 /* delete inotify variable */
1015                 ecore_main_fd_handler_del(g_fd_handler_lang);
1016                 inotify_rm_watch(g_fd_lang, g_wd_lang);
1017                 close(g_fd_lang);
1018                 g_fd_handler_lang = NULL;
1019                 g_fd_lang = -1;
1020
1021                 vconf_ignore_key_changed(VCONFKEY_LANGSET, language_changed_cb);
1022         }
1023
1024         return VC_CONFIG_ERROR_NONE;
1025 }
1026
1027 int vc_config_mgr_set_engine_cb(unsigned int uid, vc_config_engine_changed_cb engine_cb)
1028 {
1029         if (nullptr == engine_cb) {
1030                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enagine cb is NULL : uid(%u) ", uid);
1031                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1032         }
1033
1034         ecore_thread_main_loop_begin();
1035         if (false == g_VoiceControlClients->isUidValid(uid)) {
1036                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
1037                 ecore_thread_main_loop_end();
1038                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1039         }
1040
1041         g_VoiceControlClients->setEngineChangedCallback(uid, engine_cb);
1042
1043         if (VC_CONFIG_ERROR_NONE != register_language_config_changed_event()) {
1044                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to register config event");
1045                 ecore_thread_main_loop_end();
1046                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1047         }
1048
1049         ecore_thread_main_loop_end();
1050         return VC_CONFIG_ERROR_NONE;
1051 }
1052
1053 int vc_config_mgr_unset_engine_cb(unsigned int uid)
1054 {
1055         ecore_thread_main_loop_begin();
1056         if (false == g_VoiceControlClients->isUidValid(uid)) {
1057                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
1058                 ecore_thread_main_loop_end();
1059                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1060         }
1061
1062         g_VoiceControlClients->setEngineChangedCallback(uid, nullptr);
1063
1064         unregister_language_config_event();
1065
1066         ecore_thread_main_loop_end();
1067         return VC_CONFIG_ERROR_NONE;
1068 }
1069
1070 int vc_config_mgr_set_lang_cb(unsigned int uid, vc_config_lang_changed_cb lang_cb)
1071 {
1072         if (nullptr == lang_cb) {
1073                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enagine cb is NULL : uid(%u) ", uid);
1074                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1075         }
1076
1077         ecore_thread_main_loop_begin();
1078         if (false == g_VoiceControlClients->isUidValid(uid)) {
1079                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
1080                 ecore_thread_main_loop_end();
1081                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1082         }
1083
1084         g_VoiceControlClients->setLanguageChangedCallback(uid, lang_cb);
1085         ecore_thread_main_loop_end();
1086         return VC_CONFIG_ERROR_NONE;
1087 }
1088
1089 int vc_config_mgr_unset_lang_cb(unsigned int uid)
1090 {
1091         ecore_thread_main_loop_begin();
1092         if (false == g_VoiceControlClients->isUidValid(uid)) {
1093                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
1094                 ecore_thread_main_loop_end();
1095                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1096         }
1097
1098         g_VoiceControlClients->setLanguageChangedCallback(uid, nullptr);
1099         ecore_thread_main_loop_end();
1100         return VC_CONFIG_ERROR_NONE;
1101 }
1102
1103 int vc_config_mgr_set_enabled_cb(unsigned int uid, vc_config_enabled_cb enabled_cb)
1104 {
1105         if (NULL == enabled_cb) {
1106                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] enabled cb is NULL : uid(%u) ", uid);
1107                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1108         }
1109
1110         if (false == g_VoiceControlClients->isUidValid(uid)) {
1111                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
1112                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1113         }
1114
1115         g_VoiceControlClients->setEnabledChangedCallback(uid, enabled_cb);
1116         return VC_CONFIG_ERROR_NONE;
1117 }
1118
1119 int vc_config_mgr_unset_enabled_cb(unsigned int uid)
1120 {
1121         if (false == g_VoiceControlClients->isUidValid(uid)) {
1122                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no valid client : uid(%u) ", uid);
1123                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1124         }
1125
1126         g_VoiceControlClients->setEnabledChangedCallback(uid, nullptr);
1127         return VC_CONFIG_ERROR_NONE;
1128 }
1129
1130 int vc_config_mgr_get_auto_language(bool* value)
1131 {
1132         if (g_config_mgr_initialized.load() == false) {
1133                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1134                 return VC_CONFIG_ERROR_INVALID_STATE;
1135         }
1136
1137         if (NULL == value) {
1138                 return VC_ERROR_INVALID_PARAMETER;
1139         }
1140
1141         *value = g_VoiceControlConfig->isAutoLanguageEnabled();
1142         return VC_CONFIG_ERROR_NONE;
1143 }
1144
1145 int vc_config_mgr_set_auto_language(bool value)
1146 {
1147         if (g_config_mgr_initialized.load() == false) {
1148                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1149                 return VC_CONFIG_ERROR_INVALID_STATE;
1150         }
1151
1152         if (g_VoiceControlConfig->isAutoLanguageEnabled() != value) {
1153                 /* Check language is valid */
1154                 if (0 != vc_parser_set_auto_lang(value)) {
1155                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save engine id");
1156                         return VC_CONFIG_ERROR_OPERATION_FAILED;
1157                 }
1158                 g_VoiceControlConfig->setAutoLanguageEnabled(value);
1159
1160                 if (true == value) {
1161                         set_language_by_automatic_selection();
1162                 }
1163         }
1164
1165         return VC_CONFIG_ERROR_NONE;
1166 }
1167
1168 int vc_config_mgr_get_engine_list(vc_config_supported_engine_cb callback, void* user_data)
1169 {
1170         if (g_config_mgr_initialized.load() == false) {
1171                 SLOG(LOG_ERROR, vc_config_tag(), "Not initialized");
1172                 return VC_CONFIG_ERROR_INVALID_STATE;
1173         }
1174
1175         if (NULL == callback) {
1176                 SLOG(LOG_ERROR, vc_config_tag(), " callback is NULL");
1177                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1178         }
1179
1180         if (g_VoiceControlEngines->isEngineEmpty()) {
1181                 SLOG(LOG_WARN, vc_config_tag(), "[ERROR] Engine list is NULL");
1182                 return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
1183         }
1184
1185         auto engines = g_VoiceControlEngines->getEngines();
1186         for (auto &engineInfo : engines) {
1187                 if (false == g_VoiceControlEngines->isEngineIdValid(engineInfo.getEngineId())) {
1188                         SLOG(LOG_WARN, vc_config_tag(), "Engine info is not valid. (%s)", engineInfo.getEngineId().c_str());
1189                         continue;
1190                 }
1191
1192                 if (false == callback(engineInfo.getEngineName().c_str(), engineInfo.getEngineId().c_str(), engineInfo.getSettingPath().c_str(),
1193                                 engineInfo.getDefaultLanguage().c_str(), engineInfo.isNonFixedSupported(), user_data)) {
1194                         SLOG(LOG_DEBUG, vc_config_tag(), "Callback returns false. (%s)", engineInfo.getEngineId().c_str());
1195                         break;
1196                 }
1197         }
1198
1199         return VC_CONFIG_ERROR_NONE;
1200 }
1201
1202
1203 int vc_config_mgr_get_engine(char** engine)
1204 {
1205         if (g_config_mgr_initialized.load() == false) {
1206                 SLOG(LOG_ERROR, vc_config_tag(), "Not initialized"); //LCOV_EXCL_LINE
1207                 return VC_CONFIG_ERROR_INVALID_STATE;
1208         }
1209
1210         if (NULL == engine) {
1211                 SLOG(LOG_ERROR, vc_config_tag(), "Parameter is NULL");
1212                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1213         }
1214
1215         string default_engine_id = g_VoiceControlConfig->getEngineId();
1216         if (default_engine_id.empty()) {
1217                 SLOG(LOG_ERROR, vc_config_tag(), " Engine id is NULL"); //LCOV_EXCL_LINE
1218                 return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
1219         }
1220         *engine = strdup(default_engine_id.c_str());
1221
1222         return VC_CONFIG_ERROR_NONE;
1223 }
1224
1225 static int set_default_engine_id_on_buxtonkey(const char* engine)
1226 {
1227         /* Set vconfkey */
1228         struct buxton_client * bux_cli;
1229         struct buxton_layer * bux_layer;
1230         struct buxton_value * bux_val;
1231
1232         int ret = buxton_open(&bux_cli, NULL, NULL);
1233         if (0 != ret) {
1234                 SLOG(LOG_ERROR, vc_config_tag(), "[DBUS-BUXTON2] Fail to open buxton client, ret(%d)", ret);
1235                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1236         }
1237         bux_layer = buxton_create_layer("system");
1238         if (NULL == bux_layer) {
1239                 SLOG(LOG_ERROR, vc_config_tag(), "[DBUS-BUXTON2] buxton_create_layer FAIL");
1240                 buxton_close(bux_cli);
1241                 bux_cli = NULL;
1242                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1243         }
1244         bux_val = buxton_value_create_string(engine);
1245         if (NULL == bux_val) {
1246                 SLOG(LOG_ERROR, vc_config_tag(), "[DBUS-BUXTON2] buxton_value_create_string FAIL");
1247                 buxton_free_layer(bux_layer);
1248                 buxton_close(bux_cli);
1249                 bux_layer = NULL;
1250                 bux_cli = NULL;
1251                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1252         } else {
1253                 SLOG(LOG_DEBUG, vc_config_tag(), "[DBUS-BUXTON2] layer: %s", buxton_layer_get_name(bux_layer));
1254         }
1255
1256         ret = buxton_set_value_sync(bux_cli, bux_layer, VC_ENGINE_DB_DEFAULT, bux_val);
1257         if (0 != ret) {
1258                 SLOG(LOG_ERROR, vc_config_tag(), "[DBUS-BUXTON2] Fail to set value sync, ret(%d)", ret);
1259                 buxton_value_free(bux_val);
1260                 buxton_free_layer(bux_layer);
1261                 buxton_close(bux_cli);
1262
1263                 bux_cli = NULL;
1264                 bux_layer = NULL;
1265                 bux_val = NULL;
1266                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1267         }
1268         SLOG(LOG_DEBUG, vc_config_tag(), "[DBUS-BUXTON2] buxton_set_value_sync: %s", VC_ENGINE_DB_DEFAULT);
1269
1270         buxton_value_free(bux_val);
1271         buxton_free_layer(bux_layer);
1272         buxton_close(bux_cli);
1273
1274         bux_cli = NULL;
1275         bux_layer = NULL;
1276         bux_val = NULL;
1277
1278         return VC_CONFIG_ERROR_NONE;
1279 }
1280
1281 int vc_config_mgr_set_engine(const char* engine)
1282 {
1283         if (g_config_mgr_initialized.load() == false) {
1284                 SLOG(LOG_ERROR, vc_config_tag(), "Not initialized");
1285                 return VC_CONFIG_ERROR_INVALID_STATE;
1286         }
1287
1288         if (NULL == engine) {
1289                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1290         }
1291
1292         /* Check current engine id with new engine id */
1293         string default_engine_id = g_VoiceControlConfig->getEngineId();
1294         if (0 == default_engine_id.compare(engine)) {
1295                 return VC_CONFIG_ERROR_NONE;
1296         }
1297
1298         SLOG(LOG_DEBUG, vc_config_tag(), "New engine id : %s", engine);
1299
1300         int ret = set_default_engine_id_on_buxtonkey(engine);
1301         if (0 != ret) {
1302                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] set buxtonkey Failed!!!");
1303                 return ret;
1304         }
1305
1306         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(engine);
1307         if (nullptr == engineInfo) {
1308                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", engine);
1309                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1310         }
1311
1312         if (0 != vc_parser_set_engine(engine)) {
1313                 SLOG(LOG_ERROR, vc_config_tag(), " Fail to save config");
1314                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1315         }
1316         notify_engine_changed(engine);
1317         g_VoiceControlConfig->setEngineId(engine);
1318
1319         /* Engine is valid*/
1320         string default_language = g_VoiceControlConfig->getCurrentLanguage();
1321         bool is_language_valid = engineInfo->isLanguageValid(default_language);
1322         SLOG(LOG_ERROR, vc_config_tag(), "[INFO] Language(%s), is valid(%d)", default_language.c_str(), (int)is_language_valid);
1323
1324         if (false == is_language_valid) {
1325                 auto languages = engineInfo->getSupportedLanguages();
1326                 if (languages.empty()) {
1327                         SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to get default language. Engine id(%s) is not valid", engine);
1328                         return VC_CONFIG_ERROR_OPERATION_FAILED;
1329                 }
1330
1331                 g_VoiceControlConfig->setCurrentLanguage(languages[0].c_str());
1332         }
1333
1334         SLOG(LOG_DEBUG, vc_config_tag(), "[Config] Engine changed");
1335         g_VoiceControlConfig->printOutConfig();
1336         return VC_CONFIG_ERROR_NONE;
1337 }
1338
1339 int vc_config_mgr_get_language_list(vc_supported_language_cb callback, void* user_data)
1340 {
1341         if (g_config_mgr_initialized.load() == false) {
1342                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1343                 return VC_CONFIG_ERROR_INVALID_STATE;
1344         }
1345
1346         if (nullptr == callback) {
1347                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Callback is null");
1348                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1349         }
1350
1351         string default_engine_id = g_VoiceControlConfig->getEngineId();
1352         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(default_engine_id);
1353         if (nullptr == engineInfo) {
1354                 SLOG(LOG_ERROR, vc_config_tag(), "Fail to find engine information : %s", default_engine_id.c_str());
1355                 return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
1356         }
1357
1358         /* Get a first item */
1359         auto languages = engineInfo->getSupportedLanguages();
1360         for (auto &language : languages) {
1361                 SLOG(LOG_INFO, vc_config_tag(), "language (%s)", language.c_str());
1362                 if (language.empty()) {
1363                         SLOG(LOG_WARN, vc_config_tag(), "Language is not valid");
1364                         continue;
1365                 }
1366
1367                 if (false == callback(language.c_str(), user_data)) {
1368                         SLOG(LOG_DEBUG, vc_config_tag(), "Callback returns false (%s)", language.c_str());
1369                         break;
1370                 }
1371         }
1372
1373         return VC_CONFIG_ERROR_NONE;
1374 }
1375
1376 int vc_config_mgr_get_default_language(char** language)
1377 {
1378         if (g_config_mgr_initialized.load() == false) {
1379                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1380                 return VC_CONFIG_ERROR_INVALID_STATE;
1381         }
1382
1383         if (NULL == language) {
1384                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1385         }
1386
1387         string default_language = g_VoiceControlConfig->getCurrentLanguage();
1388         if (default_language.empty()) {
1389                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] language is NULL");
1390                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1391         }
1392
1393         *language = strdup(default_language.c_str());
1394         return VC_CONFIG_ERROR_NONE;
1395 }
1396
1397 static int set_current_language(const char* language)
1398 {
1399         if (g_config_mgr_initialized.load() == false) {
1400                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1401                 return VC_CONFIG_ERROR_INVALID_STATE;
1402         }
1403
1404         if (NULL == language) {
1405                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1406         }
1407
1408         /* Check language is valid */
1409         string default_language = g_VoiceControlConfig->getCurrentLanguage();
1410         if (default_language.empty()) {
1411                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] language is NULL");
1412                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1413         }
1414
1415         if (0 != vc_parser_set_language(language)) {
1416                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to save engine id");
1417                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1418         }
1419         notify_language_changed(default_language.c_str(), language);
1420         g_VoiceControlConfig->setCurrentLanguage(language);
1421
1422         return VC_CONFIG_ERROR_NONE;
1423 }
1424
1425 int vc_config_mgr_set_default_language(const char* language)
1426 {
1427         int ret = set_current_language(language);
1428         return ret;
1429 }
1430
1431 int vc_config_mgr_get_enabled(bool* value)
1432 {
1433         if (g_config_mgr_initialized.load() == false) {
1434                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1435                 return VC_CONFIG_ERROR_INVALID_STATE;
1436         }
1437
1438         if (NULL == value) {
1439                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1440         }
1441
1442         *value = g_VoiceControlConfig->isEnabled();
1443         return VC_CONFIG_ERROR_NONE;
1444 }
1445
1446 int vc_config_mgr_set_enabled(bool value)
1447 {
1448         if (g_config_mgr_initialized.load() == false) {
1449                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1450                 return VC_CONFIG_ERROR_INVALID_STATE;
1451         }
1452
1453         if (0 != vc_parser_set_enabled(value)) {
1454                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Fail to set enabled");
1455                 return VC_CONFIG_ERROR_OPERATION_FAILED;
1456         }
1457         notify_enabled_changed(value);
1458         g_VoiceControlConfig->setEnabled(value);
1459
1460         return VC_CONFIG_ERROR_NONE;
1461 }
1462
1463 int vc_config_mgr_get_nonfixed_support(bool* value)
1464 {
1465         if (g_config_mgr_initialized.load() == false) {
1466                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1467                 return VC_CONFIG_ERROR_INVALID_STATE;
1468         }
1469
1470         if (NULL == value) {
1471                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Input parameter is NULL");
1472                 return VC_CONFIG_ERROR_INVALID_PARAMETER;
1473         }
1474
1475         string default_engine_id = g_VoiceControlConfig->getEngineId();
1476         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(default_engine_id);
1477         if (nullptr == engineInfo) {
1478                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", default_engine_id.c_str());
1479                 return VC_CONFIG_ERROR_ENGINE_NOT_FOUND;
1480         };
1481
1482         *value = engineInfo->isNonFixedSupported();
1483         return VC_CONFIG_ERROR_NONE;
1484 }
1485
1486 bool vc_config_check_default_engine_is_valid(const char* engine)
1487 {
1488         if (g_config_mgr_initialized.load() == false) {
1489                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1490                 return false;
1491         }
1492
1493         bool is_engine_valid = g_VoiceControlEngines->isEngineIdValid(engine);
1494         return is_engine_valid;
1495 }
1496
1497 bool vc_config_check_default_language_is_valid(const char* language)
1498 {
1499         if (g_config_mgr_initialized.load() == false) {
1500                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1501                 return false;
1502         }
1503
1504         if (NULL == language) {
1505                 return false;
1506         }
1507
1508         string default_engine_id = g_VoiceControlConfig->getEngineId();
1509         shared_ptr<VoiceControlEngineInfo> engineInfo = g_VoiceControlEngines->getEngineInfo(default_engine_id);
1510         if (nullptr == engineInfo) {
1511                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] There is no engine with id (%s)!!", default_engine_id.c_str());
1512                 return false;
1513         };
1514
1515         bool is_language_valid = engineInfo->isLanguageValid(language);
1516         SLOG(LOG_INFO, vc_config_tag(), "[INFO] Language(%s), is valid(%d)", language, (int)is_language_valid);
1517
1518         return is_language_valid;
1519 }
1520
1521 int vc_config_mgr_set_foreground(int pid, bool value)
1522 {
1523         if (g_config_mgr_initialized.load() == false) {
1524                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1525                 return VC_CONFIG_ERROR_INVALID_STATE;
1526         }
1527
1528         return vc_parser_set_foreground(pid, value);
1529 }
1530
1531 int vc_config_mgr_get_foreground(int* pid)
1532 {
1533         if (g_config_mgr_initialized.load() == false) {
1534                 SLOG(LOG_ERROR, vc_config_tag(), "[ERROR] Not initialized");
1535                 return VC_CONFIG_ERROR_INVALID_STATE;
1536         }
1537
1538         return vc_parser_get_foreground(pid);
1539 }