Add to release memory for sound data
[platform/core/uifw/tts.git] / engine-parser / src / tts-engine-parser.c
1 //
2 // Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 #include <app_manager.h>
18 #include <dlog.h>
19 #include <errno.h>
20 #include <glib.h>
21 #include <libxml/parser.h>
22 #include <libxml/tree.h>
23 #include <pkgmgr-info.h>
24 #include <pkgmgr_installer_info.h>
25 #include <stdio.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <tzplatform_config.h>
30 #include <systemd/sd-login.h>
31
32 #include <gum/gum-user.h>
33 #include <gum/gum-user-service.h>
34 #include <gum/common/gum-user-types.h>
35
36 /* Define EXPORT_API */
37 #ifndef EXPORT_API
38 #define EXPORT_API __attribute__((visibility("default")))
39 #endif
40
41 #ifdef LOG_TAG
42 #undef LOG_TAG
43 #endif
44 #define LOG_TAG "tts-engine-parser"
45
46 #define TTS_TAG_ENGINE_BASE                     "tts-engine"
47 #define TTS_TAG_ENGINE_NAME                     "name"
48 #define TTS_TAG_ENGINE_ID                       "id"
49 #define TTS_TAG_ENGINE_SETTING                  "setting"
50 #define TTS_TAG_ENGINE_VOICE_SET                "voices"
51 #define TTS_TAG_ENGINE_VOICE                    "voice"
52 #define TTS_TAG_ENGINE_VOICE_TYPE               "type"
53 #define TTS_TAG_ENGINE_PITCH_SUPPORT            "pitch-support"
54 #define TTS_TAG_ENGINE_CREDENTIAL               "credential"
55
56 #define TTS_CONFIG_BASE         tzplatform_mkpath(TZ_USER_HOME, "share/.voice")
57 #define TTS_HOME                tzplatform_mkpath(TZ_USER_HOME, "share/.voice/tts")
58 #define TTS_ENGINE_BASE         tzplatform_mkpath(TZ_USER_HOME, "share/.voice/tts/1.0")
59 #define TTS_ENGINE_INFO         tzplatform_mkpath(TZ_USER_SHARE, ".voice/tts/1.0/engine-info")
60
61 #define TTS_GLOBAL_CONFIG_BASE          "/etc/skel/share/.voice"
62 #define TTS_GLOBAL_HOME         "/etc/skel/share/.voice/tts"
63 #define TTS_GLOBAL_ENGINE_BASE          "/etc/skel/share/.voice/tts/1.0"
64 #define TTS_GLOBAL_ENGINE_INFO          "/etc/skel/share/.voice/tts/1.0/engine-info"
65
66 #define TTS_METADATA_NAME                       "http://tizen.org/metadata/tts-engine/name"
67 #define TTS_METADATA_LANGUAGE                   "http://tizen.org/metadata/tts-engine/language"
68 #define TTS_METADATA_CREDENTIAL_REQUIRED        "http://tizen.org/metadata/tts-engine/credential-required"
69 #define TTS_METADATA_SETTING            "http://tizen.org/metadata/tts-engine/setting"
70
71 /* Define Macro */
72 #define FREE(x) { if (NULL != x)        { free(x);      x = NULL; } }
73 #define G_FREE(x)       { if (NULL != x) { g_free(x);   x = NULL; } }
74
75 typedef struct metadata {
76         const char *key;
77         const char *value;
78 } metadata;
79
80 static xmlDocPtr g_doc;
81 GumUser *g_guser = NULL;
82 uid_t g_uid = 301;      // app_fw
83 gid_t g_gid = 301;      // app_fw
84 GumUserType g_ut = GUM_USERTYPE_NONE;
85 gchar *g_user_type = NULL;
86
87 char *g_dir_config_base = NULL;
88 char *g_dir_home = NULL;
89 char *g_dir_engine_base = NULL;
90 char *g_dir_engine_info = NULL;
91
92 static int __create_engine_info_xml(const char *pkgid)
93 {
94         LOGD("=== Create engine info doc");
95         g_doc = xmlNewDoc((xmlChar*)"1.0");
96         if (NULL == g_doc) {
97                 LOGE("[ERROR] Fail to new doc");
98                 return -1;
99         }
100         LOGD("===");
101         return 0;
102 }
103
104 static int __save_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid, gid_t gid)
105 {
106         LOGD("=== Save engine info doc");
107         char *dir_config_base = NULL;
108         char *dir_home = NULL;
109         char *dir_engine_base = NULL;
110         char *dir_engine_info = NULL;
111
112         if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) {
113                 LOGE("[ERROR] Usertype is NONE");
114                 return -1;
115         }
116
117         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
118         uid_t tmp_uid = 0;
119         gid_t tmp_gid = 0;
120
121         LOGD("uid(%d)", uid);
122
123         if (globalapp_uid == uid) {
124                 /* Global app */
125                 dir_config_base = strdup(TTS_GLOBAL_CONFIG_BASE);
126                 dir_home = strdup(TTS_GLOBAL_HOME);
127                 dir_engine_base = strdup(TTS_GLOBAL_ENGINE_BASE);
128                 dir_engine_info = strdup(TTS_GLOBAL_ENGINE_INFO);
129                 tmp_uid = 301;  // app_fw
130                 tmp_gid = 301;  // app_fw
131         } else {
132                 /* User app, Guest app, Security app */
133                 if (NULL != g_dir_config_base)
134                         dir_config_base = strdup(g_dir_config_base);
135                 if (NULL != g_dir_home)
136                         dir_home = strdup(g_dir_home);
137                 if (NULL != g_dir_engine_base)
138                         dir_engine_base = strdup(g_dir_engine_base);
139                 if (NULL != g_dir_engine_info)
140                         dir_engine_info = strdup(g_dir_engine_info);
141                 tmp_uid = uid;
142                 tmp_gid = gid;
143         }
144
145         if (NULL == dir_config_base || NULL == dir_home || NULL == dir_engine_base || NULL == dir_engine_info) {
146                 LOGE("[ERROR] Fail to allocate memory");
147                 FREE(dir_config_base)
148                 FREE(dir_home)
149                 FREE(dir_engine_base)
150                 FREE(dir_engine_info)
151
152                 return -1;
153         }
154
155         LOGD("[DEBUG] dir_engine_info(%s)", dir_engine_info);
156
157
158         /* Make directories */
159 //      if (0 != access(dir_config_base, F_OK)) {
160         if (-1 == open(dir_config_base, O_DIRECTORY)) {
161                 LOGE("[INFO] No directory : %s, errno : %d", dir_config_base, errno);
162                 if (0 != mkdir(dir_config_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
163                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_config_base, errno);
164                         FREE(dir_config_base)
165                         FREE(dir_home)
166                         FREE(dir_engine_base)
167                         FREE(dir_engine_info)
168                         return -1;
169                 } else {
170                         LOGD("Success to make directory : %s", dir_config_base);
171                         if (0 != chown(dir_config_base, tmp_uid, tmp_gid)) {
172                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
173                         } else {
174                                 LOGD("[DEBUG] Success to change user and group");
175                         }
176                 }
177         }
178
179 //      if (0 != access(dir_home, F_OK)) {
180         if (-1 == open(dir_home, O_DIRECTORY)) {
181                 LOGE("[INFO] No directory : %s, errno : %d", dir_home, errno);
182                 if (0 != mkdir(dir_home, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
183                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_home, errno);
184                         FREE(dir_config_base)
185                         FREE(dir_home)
186                         FREE(dir_engine_base)
187                         FREE(dir_engine_info)
188                         return -1;
189                 } else {
190                         LOGD("Success to make directory : %s", dir_home);
191                         if (0 != chown(dir_home, tmp_uid, tmp_gid)) {
192                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
193                         } else {
194                                 LOGD("[DEBUG] Success to change user and group");
195                         }
196                 }
197         }
198
199 //      if (0 != access(dir_engine_base, F_OK)) {
200         if (-1 == open(dir_engine_base, O_DIRECTORY)) {
201                 LOGE("[INFO] No directory : %s, errno : %d", dir_engine_base, errno);
202                 if (0 != mkdir(dir_engine_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
203                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_engine_base, errno);
204                         FREE(dir_config_base)
205                         FREE(dir_home)
206                         FREE(dir_engine_base)
207                         FREE(dir_engine_info)
208                         return -1;
209                 } else {
210                         LOGD("Success to make directory : %s", dir_engine_base);
211                         if (0 != chown(dir_engine_base, tmp_uid, tmp_gid)) {
212                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
213                         } else {
214                                 LOGD("[DEBUG] Success to change user and group");
215                         }
216                 }
217         }
218
219 //      if (0 != access(dir_engine_info, F_OK)) {
220         if (-1 == open(dir_engine_info, O_DIRECTORY)) {
221                 LOGE("[INFO] No directory : %s, errno : %d", dir_engine_info, errno);
222                 if (0 != mkdir(dir_engine_info, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
223                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_engine_info, errno);
224                         FREE(dir_config_base)
225                         FREE(dir_home)
226                         FREE(dir_engine_base)
227                         FREE(dir_engine_info)
228                         return -1;
229                 } else {
230                         LOGD("Success to make directory : %s", dir_engine_info);
231                         if (0 != chown(dir_engine_info, tmp_uid, tmp_gid)) {
232                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
233                         } else {
234                                 LOGD("[DEBUG] Success to change user and group");
235                         }
236                 }
237         }
238
239
240         char path[256] = {'\0',};
241         snprintf(path, 256, "%s/%s.xml", dir_engine_info, pkgid);
242         int ret = xmlSaveFormatFile(path, g_doc, 1);
243         LOGD("xmlSaveFile (%d)", ret);
244         if (0 == ret) {
245                 if (0 != chown(path, tmp_uid, tmp_gid)) {
246                         LOGD("[ERROR] Fail to change user and group");
247                 } else {
248                         LOGD("[DEBUG] Success to change user and group");
249                 }
250         }
251
252         FREE(dir_config_base)
253         FREE(dir_home)
254         FREE(dir_engine_base)
255         FREE(dir_engine_info)
256
257         LOGD("===");
258         return 0;
259 }
260
261 static int __remove_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid)
262 {
263         LOGD("=== Remove engine info doc");
264
265         char *dir_engine_info = NULL;
266
267         if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) {
268                 LOGE("[ERROR] Usertype is NONE");
269                 return -1;
270         }
271
272         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
273
274         LOGD("uid(%d)", uid);
275
276         if (globalapp_uid == uid) {
277                 /* Global app */
278                 dir_engine_info = strdup(TTS_GLOBAL_ENGINE_INFO);
279         } else {
280                 /* User app, Guest app, Security app */
281                 if (NULL != g_dir_engine_info)
282                         dir_engine_info = strdup(g_dir_engine_info);
283         }
284
285         if (NULL == dir_engine_info) {
286                 LOGE("[ERROR] Fail to allocate memory");
287                 return -1;
288         }
289
290         LOGD("[DEBUG] dir_engine_info(%s)", dir_engine_info);
291
292
293         char path[256] = {'\0',};
294         snprintf(path, 256, "%s/%s.xml", dir_engine_info, pkgid);
295         if (0 == access(path, F_OK)) {
296                 LOGD("Remove engine info xml(%s)", path);
297                 if (0 != remove(path)) {
298                         LOGE("[ERROR] Fail to Remove engine info xml(%s)", path);
299                 }
300         }
301
302         FREE(dir_engine_info)
303
304         LOGD("===");
305         return 0;
306 }
307
308 static void __insert_language_from_metadata(xmlNodePtr root, const char *language)
309 {
310         LOGD("==== Insert language");
311         char* voice = NULL;
312         char* lang = NULL;
313         char* type = NULL;
314
315         char *tmp_lang = NULL;
316         char *tmp_free = NULL;
317         tmp_free = tmp_lang = strdup(language);
318         if (NULL == tmp_lang) {
319                 LOGE("Fail to memory allocation");
320                 return;
321         }
322         xmlNodePtr voices_node = NULL;
323         xmlNodePtr voice_node = NULL;
324
325         voices_node = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_VOICE_SET);
326
327         voice = strsep(&tmp_lang, ",");
328         while (NULL != voice) {
329                 LOGD("voice (%s)", voice);
330                 voice_node = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_VOICE);
331                 lang = strsep(&voice, ":");
332                 LOGD("lang (%s)", lang);
333                 type = strsep(&voice, " ");
334                 LOGD("type (%s)", type);
335                 xmlSetProp(voice_node, (const xmlChar*)TTS_TAG_ENGINE_VOICE_TYPE, (const xmlChar*)type);
336                 xmlNodeSetContent(voice_node, (const xmlChar*)lang);
337                 xmlAddChild(voices_node, voice_node);
338                 voice = strsep(&tmp_lang, ",");
339         }
340         xmlAddChild(root, voices_node);
341
342         FREE(tmp_lang)
343         FREE(tmp_free)
344 }
345
346 static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *list)
347 {
348         GList *iter = NULL;
349         metadata *md = NULL;
350
351         __create_engine_info_xml(pkgid);
352
353         xmlNodePtr root = NULL;
354         xmlNodePtr cur = NULL;
355
356         root = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_BASE);
357         if (NULL == root) {
358                 LOGE("[ERROR] Fail to get new node");
359 //              xmlFreeDoc(g_doc);
360                 return -1;
361         }
362         xmlDocSetRootElement(g_doc, root);
363
364         /* Save name */
365 //      cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_NAME);
366 //      xmlNodeSetContent(cur, (const xmlChar*)pkgid);
367 //      xmlAddChild(root, cur);
368
369
370         iter = g_list_first(list);
371         while (NULL != iter) {
372                 md = (metadata *)iter->data;
373                 if (NULL != md && NULL != md->key) {
374                         LOGD(" - key(%s) value(%s)", md->key, md->value);
375                         if (!strcmp(md->key, TTS_METADATA_LANGUAGE)) {
376                                 __insert_language_from_metadata(root, md->value);
377                         } else if (!strcmp(md->key, TTS_METADATA_CREDENTIAL_REQUIRED)) {
378                                 cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_CREDENTIAL);
379                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
380                                 xmlAddChild(root, cur);
381                         } else if (!strcmp(md->key, TTS_METADATA_SETTING)) {
382                                 cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_SETTING);
383                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
384                                 xmlAddChild(root, cur);
385                         } else if (!strcmp(md->key, TTS_METADATA_NAME)) {
386                                 cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_NAME);
387                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
388                                 xmlAddChild(root, cur);
389                         } else {
390                                 LOGW("[WARNING] Unknown metadata type");
391                         }
392                 }
393                 iter = g_list_next(iter);
394         }
395
396         cur = xmlNewNode(NULL, (const xmlChar*)TTS_TAG_ENGINE_ID);
397         xmlNodeSetContent(cur, (const xmlChar*)pkgid);
398         xmlAddChild(root, cur);
399
400         LOGD("");
401
402         return 0;
403
404 }
405
406 EXPORT_API
407 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
408 {
409         LOGD("METADATA INSTALL");
410         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
411
412         int ret = -1;
413         ret = pkgmgr_installer_info_get_target_uid(&g_uid);
414         if (ret < 0) {
415                 LOGE("[ERROR] Fail to get target uid");
416                 return 0;
417         } else {
418                 LOGD("uid(%d)", g_uid);
419                 printf("[Parser Debug][DEBUG] uid(%d)", g_uid);
420         }
421
422         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
423         if (globalapp_uid == g_uid) {
424                 g_user_type = g_strdup("admin");
425         } else {
426                 g_guser = gum_user_get_sync(g_uid, FALSE);
427                 if (NULL == g_guser) {
428                         LOGE("[ERROR] g_guser is NULL");
429                         return -1;
430                 }
431
432                 g_object_get(G_OBJECT(g_guser), "gid", &g_gid, NULL);
433                 g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
434                 g_user_type = g_strdup(gum_user_type_to_string(g_ut));
435         }
436
437         if (NULL == g_user_type) {
438                 LOGE("[ERROR] Fail to allocate memory");
439                 if (NULL != g_guser) {
440                         g_object_unref(g_guser);
441                         g_guser = NULL;
442                 }
443                 return -1;
444         }
445
446         if (0 == strcmp(g_user_type, "none")) {
447                 /* GUM_USERTYPE_NONE */
448                 LOGE("[ERROR] Fail to get target uid");
449                 g_object_unref(g_guser);
450                 g_guser = NULL;
451                 G_FREE(g_user_type)
452                 return -1;
453         }
454
455         if (globalapp_uid == g_uid) {
456                 /* global directory */
457                 LOGD("[DEBUG] usertype: %s", g_user_type);
458                 if (0 >= g_list_length(list)) {
459                         LOGE("[ERROR] No Engine Metadata");
460                         G_FREE(g_user_type)
461                         return 0;
462                 }
463
464                 if (0 != __write_metadata_inxml(pkgid, appid, list)) {
465                         LOGE("[ERROR] Fail to write metadata in the xml");
466                         xmlFreeDoc(g_doc);
467                         G_FREE(g_user_type)
468                         return -1;
469                 }
470
471                 /* Save in /etc/skel/share/ */
472                 g_dir_config_base = strdup(TTS_GLOBAL_CONFIG_BASE);
473                 g_dir_home = strdup(TTS_GLOBAL_HOME);
474                 g_dir_engine_base = strdup(TTS_GLOBAL_ENGINE_BASE);
475                 g_dir_engine_info = strdup(TTS_GLOBAL_ENGINE_INFO);
476
477                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
478                         LOGE("[ERROR] Fail to allocate memory");
479                         FREE(g_dir_config_base)
480                         FREE(g_dir_home)
481                         FREE(g_dir_engine_base)
482                         FREE(g_dir_engine_info)
483
484                         xmlFreeDoc(g_doc);
485                         G_FREE(g_user_type)
486                         return -1;
487                 }
488
489                 if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
490                         LOGE("[ERROR] Fail to make engine info file");
491                         xmlFreeDoc(g_doc);
492                         G_FREE(g_user_type)
493                         return -1;
494                 }
495
496                 /* Get user data by using libgum */
497
498                 GumUserService *gus = NULL;
499                 GumUserList *users = NULL;
500                 GumUserList *iter = NULL;
501                 GumUser *user = NULL;
502                 gchar **query;
503                 GumUserType gumut = GUM_USERTYPE_NONE;
504                 gchar *user_type = NULL;
505
506                 uid_t uid;
507                 gid_t gid;
508                 gchar *home_dir = NULL;
509
510                 gus = gum_user_service_create_sync(TRUE);
511                 if (!gus) {
512                         LOGE("Failed to create gum user service");
513                         G_FREE(g_user_type)
514                         return -1;
515                 }
516
517                 query = g_strsplit("admin,normal", ",", -1);
518
519                 users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
520                 g_strfreev(query);
521
522                 if (!users) {
523                         LOGE("Failed to get gum user list");
524                         g_object_unref(gus);
525                         gus = NULL;
526                         G_FREE(g_user_type)
527                         return -1;
528                 }
529
530                 /* Make new user list */
531
532                 iter = users;
533                 while (iter != NULL) {
534                         user = (GumUser*) iter->data;
535                         g_object_get(G_OBJECT(user), "uid", &uid, NULL);
536                         FREE(home_dir)
537
538                         g_object_get(G_OBJECT(user), "gid", &gid, NULL);
539                         g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
540                         g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
541                         user_type = g_strdup(gum_user_type_to_string(gumut));
542                         if (NULL == user_type) {
543                                 gum_user_service_list_free(users);
544                                 g_object_unref(gus);
545                                 gus = NULL;
546                                 return -1;
547                         }
548
549                         LOGD("[DEBUG] user info");
550                         if (NULL != home_dir) {
551                                 LOGD("[DEBUG] uid(%d), gid(%d),  user_type(%s), home_dir(%s)", uid, gid, user_type, home_dir);
552
553                                 g_dir_config_base = (char*)calloc(strlen(home_dir) + 14, sizeof(char));
554                                 g_dir_home = (char*)calloc(strlen(home_dir) + 18, sizeof(char));
555                                 g_dir_engine_base = (char*)calloc(strlen(home_dir) + 22, sizeof(char));
556                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
557
558                                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
559                                         LOGE("[ERROR] Fail to allocate memory");
560                                         FREE(g_dir_config_base)
561                                         FREE(g_dir_home)
562                                         FREE(g_dir_engine_base)
563                                         FREE(g_dir_engine_info)
564                                         gum_user_service_list_free(users);
565                                         g_object_unref(gus);
566                                         gus = NULL;
567                                         G_FREE(user_type)
568                                         return -1;
569                                 }
570                                 snprintf(g_dir_config_base, strlen(home_dir) + 14, "%s/share/.voice", home_dir);
571                                 snprintf(g_dir_home, strlen(home_dir) + 18, "%s/share/.voice/tts", home_dir);
572                                 snprintf(g_dir_engine_base, strlen(home_dir) + 22, "%s/share/.voice/tts/1.0", home_dir);
573                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/tts/1.0/engine-info", home_dir);
574
575                                 LOGD("[DEBUG] g_dir_engine_info(%s)", g_dir_engine_info);
576
577                                 if (0 != __save_engine_info_xml(pkgid, user_type, uid, gid)) {
578                                         LOGE("[ERROR] Fail to make engine info file");
579                                 }
580
581                                 FREE(g_dir_config_base)
582                                 FREE(g_dir_home)
583                                 FREE(g_dir_engine_base)
584                                 FREE(g_dir_engine_info)
585
586                                 G_FREE(user_type)
587                                 FREE(home_dir)
588
589                                 iter = g_list_next(iter);
590                         } else {
591                                 iter = g_list_next(iter);
592                         }
593
594                         G_FREE(user_type)
595                 }
596
597                 gum_user_service_list_free(users);
598                 g_object_unref(gus);
599                 gus = NULL;
600         } else {
601                 /* user directory */
602                 LOGD("[DEBUG] usertype: %s", g_user_type);
603
604                 ret = tzplatform_set_user(g_uid);
605                 if (ret < 0) {
606                         LOGE("[ERROR] Invalid uid");
607                         g_object_unref(g_guser);
608                         g_guser = NULL;
609                         G_FREE(g_user_type)
610                         return 0;
611                 } else {
612                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
613                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
614                 }
615
616                 if (0 >= g_list_length(list)) {
617                         LOGE("[ERROR] No Engine Metadata");
618                         g_object_unref(g_guser);
619                         g_guser = NULL;
620                         G_FREE(g_user_type)
621                         return 0;
622                 }
623
624                 if (0 != __write_metadata_inxml(pkgid, appid, list)) {
625                         LOGE("[ERROR] Fail to write metadata in the xml");
626                         xmlFreeDoc(g_doc);
627                         g_object_unref(g_guser);
628                         g_guser = NULL;
629                         G_FREE(g_user_type)
630                         return -1;
631                 }
632
633                 g_dir_config_base = strdup(TTS_CONFIG_BASE);
634                 g_dir_home = strdup(TTS_HOME);
635                 g_dir_engine_base = strdup(TTS_ENGINE_BASE);
636                 g_dir_engine_info = strdup(TTS_ENGINE_INFO);
637
638                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
639                         LOGE("[ERROR] Fail to allocate memory");
640                         FREE(g_dir_config_base)
641                         FREE(g_dir_home)
642                         FREE(g_dir_engine_base)
643                         FREE(g_dir_engine_info)
644                         xmlFreeDoc(g_doc);
645                         g_object_unref(g_guser);
646                         g_guser = NULL;
647                         G_FREE(g_user_type)
648                         return -1;
649                 }
650
651                 if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
652                         LOGE("[ERROR] Fail to make engine info file");
653                         xmlFreeDoc(g_doc);
654                         if (NULL != g_guser) {
655                                 g_object_unref(g_guser);
656                                 g_guser = NULL;
657                         }
658                         G_FREE(g_user_type)
659                         return -1;
660                 }
661         }
662
663         xmlFreeDoc(g_doc);
664         if (NULL != g_guser) {
665                 g_object_unref(g_guser);
666                 g_guser = NULL;
667         }
668         G_FREE(g_user_type)
669
670         FREE(g_dir_config_base)
671         FREE(g_dir_home)
672         FREE(g_dir_engine_base)
673         FREE(g_dir_engine_info)
674
675         return 0;
676 }
677
678 EXPORT_API
679 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
680 {
681         LOGD("METADATA UNINSTALL");
682         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
683
684         int ret = -1;
685         ret = pkgmgr_installer_info_get_target_uid(&g_uid);
686         if (ret < 0) {
687                 LOGE("[ERROR] Fail to get target uid");
688                 return 0;
689         } else {
690                 LOGD("uid(%d)", g_uid);
691                 printf("[Parser Debug][DEBUG] uid(%d)", g_uid);
692         }
693
694         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
695         if (globalapp_uid == g_uid) {
696                 g_user_type = g_strdup("admin");
697         } else {
698                 g_guser = gum_user_get_sync(g_uid, FALSE);
699                 if (NULL == g_guser) {
700                         LOGE("[ERROR] g_guser is NULL");
701                         return -1;
702                 }
703
704                 g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
705                 g_user_type = g_strdup(gum_user_type_to_string(g_ut));
706         }
707
708         if (NULL == g_user_type) {
709                 LOGE("[ERROR] Fail to allocate memory");
710                 if (NULL != g_guser) {
711                         g_object_unref(g_guser);
712                         g_guser = NULL;
713                 }
714                 return -1;
715         }
716
717         if (0 == strcmp(g_user_type, "none")) {
718                 /* GUM_USERTYPE_NONE */
719                 LOGE("[ERROR] Fail to get target uid");
720                 g_object_unref(g_guser);
721                 g_guser = NULL;
722                 G_FREE(g_user_type)
723                 return -1;
724         }
725
726         if (globalapp_uid == g_uid) {
727                 /* global directory */
728                 LOGD("[DEBUG] usertype: %s", g_user_type);
729
730                 /* Remove files in /etc/skel/share/ */
731                 g_dir_engine_info = strdup(TTS_GLOBAL_ENGINE_INFO);
732                 if (NULL == g_dir_engine_info) {
733                         LOGE("[ERROR] Fail to allocate memory");
734                         G_FREE(g_user_type)
735                         return -1;
736                 }
737
738                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
739                         LOGE("[ERROR] Fail to remove engine info file");
740                 }
741
742                 /* Get user data by using libgum */
743
744                 GumUserService *gus = NULL;
745                 GumUserList *users = NULL;
746                 GumUserList *iter = NULL;
747                 GumUser *user = NULL;
748                 gchar **query;
749                 GumUserType gumut = GUM_USERTYPE_NONE;
750                 gchar *user_type = NULL;
751
752                 uid_t uid;
753                 gchar *home_dir = NULL;
754
755                 GList *md_iter = NULL;
756                 metadata *md = NULL;
757
758                 gus = gum_user_service_create_sync(TRUE);
759                 if (!gus) {
760                         LOGE("Failed to create gum user service");
761                         G_FREE(g_user_type)
762                         return -1;
763                 }
764
765                 query = g_strsplit("admin,normal", ",", -1);
766
767                 users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
768                 g_strfreev(query);
769
770                 if (!users) {
771                         LOGE("Failed to get gum user list");
772                         g_object_unref(gus);
773                         gus = NULL;
774                         G_FREE(g_user_type)
775                         return -1;
776                 }
777
778                 /* Make new user list */
779
780                 iter = users;
781                 while (iter != NULL) {
782                         user = (GumUser*) iter->data;
783                         g_object_get(G_OBJECT(user), "uid", &uid, NULL);
784                         FREE(home_dir)
785                         g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
786                         g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
787                         user_type = g_strdup(gum_user_type_to_string(gumut));
788                         if (NULL == user_type) {
789                                 gum_user_service_list_free(users);
790                                 g_object_unref(gus);
791                                 gus = NULL;
792                                 return -1;
793                         }
794
795                         if (NULL != home_dir) {
796                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
797                                 if (NULL == g_dir_engine_info) {
798                                         gum_user_service_list_free(users);
799                                         g_object_unref(gus);
800                                         gus = NULL;
801                                         G_FREE(user_type)
802                                         return -1;
803                                 }
804
805                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/tts/1.0/engine-info", home_dir);
806
807                                 md_iter = g_list_first(list);
808                                 while (NULL != md_iter) {
809                                         md = (metadata *)md_iter->data;
810                                         LOGD(" - key(%s) value(%s)", md->key, md->value);
811                                         md_iter = g_list_next(md_iter);
812                                 }
813
814                                 if (0 != __remove_engine_info_xml(pkgid, user_type, uid)) {
815                                         LOGE("[ERROR] Fail to remove engine info file");
816                                 }
817
818                                 FREE(home_dir)
819                                 FREE(g_dir_engine_info)
820                                 G_FREE(user_type)
821
822                                 LOGD("Finish release memory");
823                                 iter = g_list_next(iter);
824                                 LOGD("Finish next iter");
825                         } else {
826                                 iter = g_list_next(iter);
827                         }
828                 }
829
830                 gum_user_service_list_free(users);
831                 g_object_unref(gus);
832                 gus = NULL;
833         } else {
834                 /* user directory */
835                 LOGD("[DEBUG] usertype: %s", g_user_type);
836
837                 ret = tzplatform_set_user(g_uid);
838                 if (ret < 0) {
839                         LOGE("[ERROR] Invalid uid");
840                         g_object_unref(g_guser);
841                         g_guser = NULL;
842                         G_FREE(g_user_type)
843                         return -1;
844                 } else {
845                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
846                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
847                 }
848
849                 g_dir_engine_info = strdup(TTS_ENGINE_INFO);
850                 if (NULL == g_dir_engine_info) {
851                         LOGE("[ERROR] Fail to allocate memory");
852                         g_object_unref(g_guser);
853                         g_guser = NULL;
854                         G_FREE(g_user_type)
855                         return -1;
856                 }
857
858                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
859                         LOGE("[ERROR] Fail to remove engine info file");
860                 }
861
862         }
863
864         if (NULL != g_guser) {
865                 g_object_unref(g_guser);
866                 g_guser = NULL;
867         }
868         G_FREE(g_user_type)
869
870         FREE(g_dir_engine_info)
871
872         LOGD("");
873         return 0;
874 }
875
876 EXPORT_API
877 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
878 {
879         LOGD("METADATA UPGRADE");
880         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
881
882         PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
883         PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
884
885         LOGD("");
886         return 0;
887 }