Revert manifest to default one
[profile/ivi/download-provider.git] / src / agent / download-agent-client-mgr.c
1 /*
2  * Download Agent
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jungki Kwak <jungki.kwak@samsung.com>, Keunsoon Lee <keunsoon.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * @file                download-agent-client-mgr.c
21  * @brief               client manager module for notifying download ststus information
22  * @author              Keunsoon Lee(keunsoon.lee@samsung.com)
23  * @author              Jungki Kwak(jungki.kwak@samsung.com)
24  ***/
25
26 #include <unistd.h>
27
28 #include "download-agent-client-mgr.h"
29 #include "download-agent-debug.h"
30 #include "download-agent-utils.h"
31 #include "download-agent-file.h"
32
33 #define IS_CLIENT_Q_HAVING_DATA(QUEUE)  (QUEUE->having_data)
34
35 static client_app_mgr_t client_app_mgr;
36
37 static da_result_t __launch_client_thread(void);
38 static void *__thread_for_client_noti(void *data);
39 void __thread_clean_up_handler_for_client_thread(void *arg);
40 static void __pop_client_noti(client_noti_t **out_client_noti);
41
42 void __client_q_goto_sleep_without_lock(void);
43 void __client_q_wake_up_without_lock(void);
44 void destroy_client_noti(client_noti_t *client_noti);
45
46 da_result_t init_client_app_mgr()
47 {
48         DA_LOG_FUNC_START(ClientNoti);
49
50         if(client_app_mgr.is_init)
51                 return DA_RESULT_OK;
52
53         client_app_mgr.is_init = DA_TRUE;
54         client_app_mgr.client_app_info.is_using = DA_FALSE;
55         client_app_mgr.client_app_info.is_manual_download = DA_FALSE;
56         client_app_mgr.client_app_info.client_user_agent = DA_NULL;
57         client_app_mgr.is_thread_init = DA_FALSE;
58
59         return DA_RESULT_OK;
60 }
61
62 da_bool_t is_client_app_mgr_init(void)
63 {
64         return client_app_mgr.is_init;
65 }
66
67 da_bool_t is_client_app_mgr_manual_download(void)
68 {
69         return client_app_mgr.is_manual_download;
70 }
71
72 da_result_t reg_client_app(
73                 da_client_cb_t *da_client_callback,
74                 da_download_managing_method download_method
75                 )
76 {
77         da_result_t ret = DA_RESULT_OK;
78         client_queue_t *queue = DA_NULL;
79         client_noti_t *client_noti = DA_NULL;
80
81         DA_LOG_FUNC_START(ClientNoti);
82
83         if (client_app_mgr.client_app_info.is_using)
84                 return DA_ERR_CLIENT_IS_ALREADY_REGISTERED;
85
86         client_app_mgr.client_app_info.is_using = DA_TRUE;
87         if (download_method == DA_DOWNLOAD_MANAGING_METHOD_MANUAL)
88                 client_app_mgr.client_app_info.is_manual_download = DA_TRUE;
89         else
90                 client_app_mgr.client_app_info.is_manual_download = DA_FALSE;
91
92         memset(&(client_app_mgr.client_app_info.client_callback),
93                         0, sizeof(da_client_cb_t));
94         memcpy(&(client_app_mgr.client_app_info.client_callback),
95                         da_client_callback, sizeof(da_client_cb_t));
96
97         _da_thread_mutex_init(&(client_app_mgr.mutex_client_mgr), DA_NULL);
98
99         /* If some noti is existed at queue, delete all */
100         do {
101                 __pop_client_noti(&client_noti);
102                 destroy_client_noti(client_noti);
103         } while(client_noti != DA_NULL);
104
105         queue = &(client_app_mgr.client_queue);
106         DA_LOG_VERBOSE(ClientNoti, "client queue = %p", queue);
107         _da_thread_mutex_init(&(queue->mutex_client_queue), DA_NULL);
108         _da_thread_cond_init(&(queue->cond_client_queue), DA_NULL);
109
110         ret = __launch_client_thread();
111
112         return ret;
113 }
114
115 da_result_t dereg_client_app(void)
116 {
117         client_noti_t *client_noti = DA_NULL;
118
119         DA_LOG_FUNC_START(ClientNoti);
120
121         client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t));
122         if (!client_noti) {
123                 DA_LOG_ERR(ClientNoti, "calloc fail");
124                 return DA_ERR_FAIL_TO_MEMALLOC;
125         }
126
127         client_noti->download_id = DA_INVALID_ID;
128         client_noti->noti_type = Q_CLIENT_NOTI_TYPE_TERMINATE;
129         client_noti->next = DA_NULL;
130
131         _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr));
132         if (client_app_mgr.is_thread_init != DA_TRUE) {
133                 DA_LOG_CRITICAL(ClientNoti, "try to cancel client mgr thread id[%lu]", client_app_mgr.thread_id);
134                 if (pthread_cancel(client_app_mgr.thread_id) < 0) {
135                         DA_LOG_ERR(ClientNoti, "cancel thread is failed!!!");
136                 }
137         } else {
138                 void *t_return = NULL;
139                 DA_LOG_VERBOSE(ClientNoti, "pushing Q_CLIENT_NOTI_TYPE_TERMINATE");
140                 push_client_noti(client_noti);
141                 DA_LOG_CRITICAL(Thread, "===try to join client mgr thread id[%lu]===", client_app_mgr.thread_id);
142                 if (pthread_join(client_app_mgr.thread_id, &t_return) < 0) {
143                         DA_LOG_ERR(Thread, "join client thread is failed!!!");
144                 }
145                 DA_LOG_CRITICAL(Thread, "===thread join return[%d]===", (char*)t_return);
146         }
147         _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr));
148
149         /* ToDo: This clean up should be done at the end of client_thread. */
150         client_app_mgr.client_app_info.is_using= DA_FALSE;
151         client_app_mgr.client_app_info.is_manual_download = DA_FALSE;
152         if(client_app_mgr.client_app_info.client_user_agent) {
153                 free(client_app_mgr.client_app_info.client_user_agent);
154                 client_app_mgr.client_app_info.client_user_agent = DA_NULL;
155         }
156         _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr));
157         client_app_mgr.is_thread_init = DA_FALSE;
158         _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr));
159         _da_thread_mutex_destroy(&(client_app_mgr.mutex_client_mgr));
160         return DA_RESULT_OK;
161 }
162
163 da_result_t  send_client_da_state (int download_id, da_state state, int err)
164 {
165         client_noti_t *client_noti = DA_NULL;
166         user_notify_info_t *send_state_info = DA_NULL;
167         da_state cur_da_state;
168
169         DA_LOG_FUNC_START(ClientNoti);
170
171         DA_LOG_VERBOSE(ClientNoti, "da_state[%s], download_id[%d]", print_dl_state(state), download_id);
172
173         if (!is_valid_dl_ID(download_id)) {
174                 DA_LOG_ERR(ClientNoti, "Download ID is not valid");
175                 /* Returning DA_RESULT_OK if download_id is not valid,
176                  * because sending da_state should not effect to download flow. */
177                 return DA_RESULT_OK;
178         }
179
180         if (state_watcher_need_redirect_Q(download_id)) {
181                 state_watcher_redirect_state(download_id, state, err);
182                 return DA_RESULT_OK;
183         }
184
185         cur_da_state = GET_DL_DA_STATE(download_id);
186
187         if ((DA_STATE_SUSPENDED != state) && (cur_da_state == state)) {
188                 DA_LOG(ClientNoti, "inserting da_state is same with current da_state! Not inserting! inserting: %d, cur : %d", state, cur_da_state);
189                 return DA_RESULT_OK;
190         }
191
192         GET_DL_DA_STATE(download_id) = state;
193         DA_LOG_VERBOSE(ClientNoti, "change da_state to %d", state);
194
195         client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t));
196         if (!client_noti) {
197                 DA_LOG_ERR(ClientNoti, "calloc fail");
198                 return DA_ERR_FAIL_TO_MEMALLOC;
199         }
200
201         client_noti->download_id = download_id;
202         client_noti->user_data = GET_DL_USER_DATA(download_id);
203         client_noti->noti_type = Q_CLIENT_NOTI_TYPE_SEND_STATE;
204         client_noti->next = DA_NULL;
205
206         send_state_info = (user_notify_info_t *)&(client_noti->type.da_state_info);
207         send_state_info->da_dl_req_id = GET_DL_REQ_ID(download_id);
208         send_state_info->state = state;
209         send_state_info->err = err;
210
211         DA_LOG(ClientNoti, "pushing da_state=%d, download_id=%d, err=%d, dl_req_id=%d",
212                         state, download_id, err, GET_DL_REQ_ID(download_id));
213
214         push_client_noti(client_noti);
215
216         return DA_RESULT_OK;
217 }
218
219 da_result_t  send_client_update_downloading_info (
220                 int download_id,
221                 int dl_req_id,
222                 unsigned long int total_received_size,
223                 char *saved_path
224                 )
225 {
226         client_noti_t *client_noti = DA_NULL;
227         user_downloading_info_t *downloading_info = DA_NULL;
228
229         DA_LOG_FUNC_START(ClientNoti);
230
231         if (!is_valid_dl_ID(download_id)) {
232                 DA_LOG_ERR(ClientNoti, "Download ID is not valid");
233                 return DA_ERR_INVALID_DL_REQ_ID;
234         }
235
236         client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t));
237         if (!client_noti) {
238                 DA_LOG_ERR(ClientNoti, "calloc fail");
239                 return DA_ERR_FAIL_TO_MEMALLOC;
240         }
241
242         client_noti->download_id = download_id;
243         client_noti->user_data = GET_DL_USER_DATA(download_id);
244         client_noti->noti_type = Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO;
245         client_noti->next = DA_NULL;
246
247         downloading_info = (user_downloading_info_t *)&(client_noti->type.update_downloading_info);
248         downloading_info->da_dl_req_id = dl_req_id;
249         downloading_info->total_received_size = total_received_size;
250
251         /* These strings MUST be copied to detach __thread_for_client_noti from download_info */
252         if (saved_path)
253                 downloading_info->saved_path = strdup(saved_path);
254         DA_LOG(ClientNoti, "pushing received_size=%lu, download_id=%d, dl_req_id=%d",
255                         total_received_size, download_id, dl_req_id);
256
257         push_client_noti(client_noti);
258
259         return DA_RESULT_OK;
260 }
261
262 da_result_t  send_client_update_dl_info (
263                 int download_id,
264                 int dl_req_id,
265                 char *file_type,
266                 unsigned long int file_size,
267                 char *tmp_saved_path,
268                 char *http_response_header,
269                 char *http_chunked_data
270                 )
271 {
272         client_noti_t *client_noti = DA_NULL;
273         user_download_info_t *update_dl_info = DA_NULL;
274
275         DA_LOG_FUNC_START(ClientNoti);
276
277         if (!is_valid_dl_ID(download_id)) {
278                 DA_LOG_ERR(ClientNoti, "Download ID is not valid");
279                 return DA_ERR_INVALID_DL_REQ_ID;
280         }
281
282         client_noti = (client_noti_t *)calloc(1, sizeof(client_noti_t));
283         if (!client_noti) {
284                 DA_LOG_ERR(ClientNoti, "calloc fail");
285                 return DA_ERR_FAIL_TO_MEMALLOC;
286         }
287
288         client_noti->download_id = download_id;
289         client_noti->user_data = GET_DL_USER_DATA(download_id);
290         client_noti->noti_type = Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO;
291         client_noti->next = DA_NULL;
292
293         update_dl_info = (user_download_info_t *)&(client_noti->type.update_dl_info);
294         update_dl_info->da_dl_req_id = dl_req_id;
295         update_dl_info->file_size = file_size;
296
297         /* These strings MUST be copied to detach __thread_for_client_noti from download_info */
298         if (file_type)
299                 update_dl_info->file_type = strdup(file_type);
300
301         if (tmp_saved_path)
302                 update_dl_info->tmp_saved_path = strdup(tmp_saved_path);
303
304         if (http_response_header) {
305                 update_dl_info->http_response_header = strdup(http_response_header);
306         }
307         if (http_chunked_data) {
308                 update_dl_info->http_chunked_data = calloc (1, file_size);
309                 if (update_dl_info->http_chunked_data)
310                         memcpy(update_dl_info->http_chunked_data, http_chunked_data,
311                                 file_size);
312         }
313         DA_LOG(ClientNoti, "pushing file_size=%lu, download_id=%d, dl_req_id=%d",
314                         file_size, download_id, dl_req_id);
315
316         push_client_noti(client_noti);
317
318         return DA_RESULT_OK;
319 }
320
321 da_result_t  __launch_client_thread(void)
322 {
323         pthread_t thread_id = DA_NULL;
324
325         DA_LOG_FUNC_START(Thread);
326
327         if (pthread_create(&thread_id,DA_NULL,__thread_for_client_noti,DA_NULL) < 0) {
328                 DA_LOG_ERR(Thread, "making thread failed..");
329                 return DA_ERR_FAIL_TO_CREATE_THREAD;
330         }
331         DA_LOG(Thread, "client mgr thread id[%d]", thread_id);
332         client_app_mgr.thread_id = thread_id;
333         return DA_RESULT_OK;
334 }
335
336 void destroy_client_noti(client_noti_t *client_noti)
337 {
338         if (client_noti) {
339                 if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO) {
340                         user_download_info_t *update_dl_info = DA_NULL;
341                         update_dl_info = (user_download_info_t*)&(client_noti->type.update_dl_info);
342                         if (update_dl_info->file_type) {
343                                 free(update_dl_info->file_type);
344                                 update_dl_info->file_type = DA_NULL;
345                         }
346                         if (update_dl_info->tmp_saved_path) {
347                                 free(update_dl_info->tmp_saved_path);
348                                 update_dl_info->tmp_saved_path = DA_NULL;
349                         }
350                         if (update_dl_info->http_response_header) {
351                                 free(update_dl_info->http_response_header);
352                                 update_dl_info->http_response_header = DA_NULL;
353                         }
354                         if (update_dl_info->http_chunked_data) {
355                                 free(update_dl_info->http_chunked_data);
356                                 update_dl_info->http_chunked_data = DA_NULL;
357                         }
358                 } else if (client_noti->noti_type ==
359                                 Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO) {
360                         user_downloading_info_t *downloading_info = DA_NULL;
361                         downloading_info = (user_downloading_info_t*)&(client_noti->type.update_downloading_info);
362                         if (downloading_info->saved_path) {
363                                 free(downloading_info->saved_path);
364                                 downloading_info->saved_path = DA_NULL;
365                         }
366                 }
367                 free(client_noti);
368         }
369 }
370
371
372 void push_client_noti(client_noti_t *client_noti)
373 {
374         client_queue_t *queue = DA_NULL;
375         client_noti_t *head = DA_NULL;
376         client_noti_t *pre = DA_NULL;
377         client_noti_t *cur = DA_NULL;
378
379         /* DA_LOG_FUNC_START(ClientNoti); */
380
381         if(!is_this_client_available()) {
382                 DA_LOG_ERR(ClientNoti, "invalid client");
383                 return;
384         }
385         queue = &(client_app_mgr.client_queue);
386         _da_thread_mutex_lock (&(queue->mutex_client_queue));
387
388         head = queue->client_q_head;
389         if (!head) {
390                 queue->client_q_head = client_noti;
391         } else {
392                 cur = head;
393                 while (cur->next) {
394                         pre = cur;
395                         cur = pre->next;
396                 }
397
398                 if (DA_TRUE == is_this_client_manual_download_type()) {
399                         cur->next = client_noti;
400                 } else if (client_noti->noti_type == Q_CLIENT_NOTI_TYPE_SEND_STATE) {
401                         cur->next = client_noti;
402                 } else {
403                         if (cur->noti_type == Q_CLIENT_NOTI_TYPE_SEND_STATE) {
404                                 cur->next = client_noti;
405                         } else if (cur->noti_type == Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO) {
406                                 /* For UI performance. If the update noti info is existed at queue,
407                                    replace it with new update noti info */
408                                 if (cur->download_id == client_noti->download_id) {
409                                         /* DA_LOG(ClientNoti, "exchange queue's tail and pushing item"); */
410                                         if (pre == DA_NULL)
411                                                 queue->client_q_head = client_noti;
412                                         else
413                                                 pre->next = client_noti;
414                                         destroy_client_noti(cur);
415                                 } else {
416                                         cur->next = client_noti;
417                                 }
418                         }
419                 }
420         }
421
422         queue->having_data = DA_TRUE;
423
424         __client_q_wake_up_without_lock();
425
426         _da_thread_mutex_unlock (&(queue->mutex_client_queue));
427 }
428
429 void __pop_client_noti(client_noti_t **out_client_noti)
430 {
431         client_queue_t *queue = DA_NULL;
432
433         /* DA_LOG_FUNC_START(ClientNoti); */
434
435         queue = &(client_app_mgr.client_queue);
436
437         _da_thread_mutex_lock (&(queue->mutex_client_queue));
438
439         if (queue->client_q_head) {
440                 *out_client_noti = queue->client_q_head;
441                 queue->client_q_head = queue->client_q_head->next;
442         } else {
443                 *out_client_noti = DA_NULL;
444         }
445
446         if (queue->client_q_head == DA_NULL) {
447                 queue->having_data = DA_FALSE;
448         }
449
450         _da_thread_mutex_unlock (&(queue->mutex_client_queue));
451 }
452
453 void __client_q_goto_sleep_without_lock(void)
454 {
455         client_queue_t *queue = DA_NULL;
456
457         /* DA_LOG_FUNC_START(ClientNoti); */
458
459         queue = &(client_app_mgr.client_queue);
460         _da_thread_cond_wait(&(queue->cond_client_queue), &(queue->mutex_client_queue));
461 }
462
463 void __client_q_wake_up_without_lock(void)
464 {
465         client_queue_t *queue = DA_NULL;
466
467         /* DA_LOG_FUNC_START(ClientNoti); */
468
469         queue = &(client_app_mgr.client_queue);
470         _da_thread_cond_signal(&(queue->cond_client_queue));
471 }
472
473 void __thread_clean_up_handler_for_client_thread(void *arg)
474 {
475         DA_LOG_CRITICAL(Thread, "cleanup for thread id = %d", pthread_self());
476 }
477
478 static void *__thread_for_client_noti(void *data)
479 {
480         da_result_t  ret = DA_RESULT_OK;
481         da_bool_t need_wait = DA_TRUE;
482         client_queue_t *queue = DA_NULL;
483         client_noti_t *client_noti = DA_NULL;
484
485         DA_LOG_FUNC_START(Thread);
486
487         _da_thread_mutex_lock(&(client_app_mgr.mutex_client_mgr));
488         client_app_mgr.is_thread_init = DA_TRUE;
489         _da_thread_mutex_unlock(&(client_app_mgr.mutex_client_mgr));
490
491         queue = &(client_app_mgr.client_queue);
492         DA_LOG(ClientNoti, "client queue = %p", queue);
493
494         pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, DA_NULL);
495         pthread_cleanup_push(__thread_clean_up_handler_for_client_thread, (void *)DA_NULL);
496
497         do {
498                 _da_thread_mutex_lock(&(queue->mutex_client_queue));
499                 if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) {
500                         DA_LOG(Thread, "Sleep @ thread_for_client_noti!");
501                         __client_q_goto_sleep_without_lock();
502                         DA_LOG(Thread, "Woke up @ thread_for_client_noti");
503                 }
504                 _da_thread_mutex_unlock(&(queue->mutex_client_queue));
505
506                 do {
507                         __pop_client_noti(&client_noti);
508                         if (client_noti == DA_NULL) {
509                                 DA_LOG_ERR(ClientNoti, "There is no data on client queue!");
510                                 ret = DA_ERR_INVALID_STATE;
511                                 need_wait = DA_FALSE;
512                         } else {
513                                 switch (client_noti->noti_type) {
514                                 case Q_CLIENT_NOTI_TYPE_UPDATE_DL_INFO:
515                                 {
516                                         user_download_info_t *update_dl_info = DA_NULL;;
517                                         update_dl_info = (user_download_info_t*)(&(client_noti->type.update_dl_info));
518                                         if (client_app_mgr.client_app_info.client_callback.update_dl_info_cb) {
519                                                 client_app_mgr.client_app_info.client_callback.update_dl_info_cb(update_dl_info, client_noti->user_data);
520                                                 DA_LOG(ClientNoti, "Update download info for download_id=%d, dl_req_id=%d, received size=%lu- DONE",
521                                                                 client_noti->download_id,
522                                                                 update_dl_info->da_dl_req_id,
523                                                                 update_dl_info->file_size
524                                                                 );
525                                         }
526                                 }
527                                 break;
528                                 case Q_CLIENT_NOTI_TYPE_UPDATE_DOWNLOADING_INFO:
529                                 {
530                                         user_downloading_info_t *downloading_info = DA_NULL;;
531                                         downloading_info = (user_downloading_info_t*)(&(client_noti->type.update_downloading_info));
532                                         if (client_app_mgr.client_app_info.client_callback.update_progress_info_cb) {
533                                                 client_app_mgr.client_app_info.client_callback.update_progress_info_cb(downloading_info, client_noti->user_data);
534                                                 DA_LOG(ClientNoti, "Update downloading info for download_id=%d, dl_req_id=%d, received size=%lu - DONE",
535                                                                 client_noti->download_id,
536                                                                 downloading_info->da_dl_req_id,
537                                                                 downloading_info->total_received_size);
538                                         }
539                                 }
540                                 break;
541                                 case Q_CLIENT_NOTI_TYPE_SEND_STATE:
542                                 {
543                                         user_notify_info_t *da_state_info = DA_NULL;
544                                         da_state_info = (user_notify_info_t *)(&(client_noti->type.da_state_info));
545
546                                         if (client_app_mgr.client_app_info.client_callback.user_noti_cb) {
547                                                 DA_LOG(ClientNoti, "User Noti info for download_id=%d, dl_req_id=%d, da_state=%d, err=%d",
548                                                                 client_noti->download_id,
549                                                                 da_state_info->da_dl_req_id, da_state_info->state,
550                                                                 da_state_info->err);
551                                                 client_app_mgr.client_app_info.client_callback.user_noti_cb(da_state_info, client_noti->user_data);
552                                                 DA_LOG(ClientNoti, "User Noti info for download_id=%d, dl_req_id=%d, da_state=%d, err=%d - DONE",
553                                                                 client_noti->download_id,
554                                                                 da_state_info->da_dl_req_id,
555                                                                 da_state_info->state, da_state_info->err);
556                                         }
557                                 }
558                                 break;
559                                 case Q_CLIENT_NOTI_TYPE_TERMINATE:
560                                         DA_LOG_CRITICAL(ClientNoti, "Q_CLIENT_NOTI_TYPE_TERMINATE");
561                                         need_wait = DA_FALSE;
562                                         break;
563                                 }
564                                 destroy_client_noti(client_noti);
565                         }
566
567                         if(DA_TRUE == need_wait) {
568                                 _da_thread_mutex_lock(&(queue->mutex_client_queue));
569                                 if (DA_FALSE == IS_CLIENT_Q_HAVING_DATA(queue)) {
570                                         _da_thread_mutex_unlock (&(queue->mutex_client_queue));
571                                         break;
572                                 } else {
573                                         _da_thread_mutex_unlock (&(queue->mutex_client_queue));
574                                 }
575                         } else {
576                                 break;
577                         }
578                 } while (1);
579         } while (DA_TRUE == need_wait);
580
581         _da_thread_mutex_destroy(&(queue->mutex_client_queue));
582         _da_thread_cond_destroy(&(queue->cond_client_queue));
583
584         pthread_cleanup_pop(0);
585         DA_LOG_CRITICAL(Thread, "=====thread_for_client_noti- EXIT=====");
586         pthread_exit((void *)NULL);
587         return DA_NULL;
588 }
589
590 da_bool_t is_this_client_available(void)
591 {
592         return client_app_mgr.client_app_info.is_using;
593 }
594
595 da_bool_t is_this_client_manual_download_type(void)
596 {
597         return client_app_mgr.client_app_info.is_manual_download;
598 }
599
600 da_result_t  get_client_download_path(char **out_path)
601 {
602         if (!out_path) {
603                 DA_LOG_ERR(ClientNoti, "DA_ERR_INVALID_ARGUMENT");
604                 return DA_ERR_INVALID_ARGUMENT;
605         }
606
607         /* change the directory policy. it doesn't clean the temp direcoty when deinitializing */
608         *out_path = strdup(DA_DEFAULT_TMP_FILE_DIR_PATH);
609         DA_LOG_VERBOSE(ClientNoti, "client download path = [%s]", *out_path);
610
611         return DA_RESULT_OK;
612 }
613
614 char *get_client_user_agent_string(void)
615 {
616         if (!client_app_mgr.is_init)
617                 return DA_NULL;
618
619         return client_app_mgr.client_app_info.client_user_agent;
620 }