Git init
[framework/api/application.git] / src / ui_notification.c
1 /*
2  * Copyright (c) 2011 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 <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdarg.h>
22 #include <sys/stat.h>
23
24 #include <dlog.h>
25 #include <notification.h>
26
27 #include <app_service.h>
28 #include <app_service_private.h>
29 #include <app_ui_notification.h>
30
31 #ifdef LOG_TAG
32 #undef LOG_TAG
33 #endif
34
35 #define LOG_TAG "TIZEN_N_UI_NOTIFICATION"
36
37 struct ui_notification_s {
38         notification_h core;
39         bool ongoing;
40         bool posted;
41         char *icon;
42         struct tm *time;
43         char *title;
44         char *content;
45         service_h service;
46 };
47
48 static int ui_notification_error_handler(int error, const char *func, const char *on_error)
49 {
50         int retcode;
51         char *error_msg;
52
53         switch (error)
54         {
55         case NOTIFICATION_ERROR_NONE:
56                 retcode = UI_NOTIFICATION_ERROR_NONE;
57                 break;
58
59         case NOTIFICATION_ERROR_INVALID_DATA:
60                 retcode = UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
61                 error_msg = "INVALID_PARAMETER";
62                 break;
63
64         case NOTIFICATION_ERROR_NO_MEMORY:
65                 retcode = UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
66                 error_msg = "OUT_OF_MEMORY";
67                 break;
68
69         case NOTIFICATION_ERROR_FROM_DB:
70                 retcode = UI_NOTIFICATION_ERROR_DB_FAILED;
71                 error_msg = "DB_FAILED";
72                 break;          
73
74         case NOTIFICATION_ERROR_ALREADY_EXIST_ID:
75                 retcode = UI_NOTIFICATION_ERROR_ALREADY_POSTED;
76                 error_msg = "ALREADY_POSTED";
77                 break;
78
79         default:
80                 retcode = UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
81                 error_msg = "INVALID_PARAMETER";
82         }
83
84         if (retcode != UI_NOTIFICATION_ERROR_NONE)
85         {
86                 LOGE("[%s] %s(0x%08x) : %s", func, error_msg, retcode, on_error);
87         }
88
89         return retcode;
90 }
91
92
93 int ui_notification_create(bool ongoing, ui_notification_h *notification)
94 {
95         ui_notification_h notification_out;
96
97         if (notification == NULL)
98         {
99                 LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid output param", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
100                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
101         }
102
103         notification_out = (ui_notification_h)malloc(sizeof(struct ui_notification_s));
104
105         if (notification_out == NULL)
106         {
107                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
108                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
109         }
110
111         notification_out->ongoing = ongoing;
112         notification_out->posted = false;
113         notification_out->icon = NULL;
114         notification_out->time = NULL;
115         notification_out->title = NULL;
116         notification_out->content = NULL;
117         notification_out->service = NULL;
118         
119         *notification = notification_out;
120
121         return UI_NOTIFICATION_ERROR_NONE;
122 }
123
124 int ui_notification_destroy(ui_notification_h notification)
125 {
126         if (notification == NULL)
127         {
128                 LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid handle", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
129                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
130         }
131
132         if (notification->core)
133                 notification_free(notification->core);
134
135         if (notification->icon)
136                 free(notification->icon);
137
138         if (notification->time)
139                 free(notification->time);
140
141         if (notification->title)
142                 free(notification->title);
143
144         if (notification->content)
145                 free(notification->content);
146
147         if (notification->service)
148                 service_destroy(notification->service);
149
150         free(notification);
151
152         return UI_NOTIFICATION_ERROR_NONE;
153 }
154
155
156 int ui_notification_set_icon(ui_notification_h notification, const char *path)
157 {
158         char *path_dup;
159
160         if (notification == NULL || path == NULL)
161         {
162                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
163                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
164         }
165
166         if (notification->posted == true)
167         {
168                 LOGE("[%s] ALREADY_POSTED(0x%08x) : unable to change the notification", __FUNCTION__, UI_NOTIFICATION_ERROR_ALREADY_POSTED);
169                 return UI_NOTIFICATION_ERROR_ALREADY_POSTED;
170         }
171
172         path_dup = strdup(path);
173
174         if (path_dup == NULL)
175         {
176                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
177                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
178         }
179
180         if (notification->icon != NULL)
181         {
182                 free(notification->icon);
183         }
184
185         notification->icon = path_dup;
186
187         return UI_NOTIFICATION_ERROR_NONE;
188 }
189
190 int ui_notification_get_icon(ui_notification_h notification, char **path)
191 {
192         char *path_dup = NULL;
193
194         if (notification == NULL || path == NULL)
195         {
196                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
197                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
198         }
199
200         if (notification->icon != NULL)
201         {
202                 path_dup = strdup(notification->icon);
203
204                 if (path_dup == NULL)
205                 {
206                         LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
207                         return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
208                 }
209         }
210
211         *path = path_dup;
212
213         return UI_NOTIFICATION_ERROR_NONE;
214 }
215
216 int ui_notification_set_time(ui_notification_h notification, struct tm *time)
217 {
218         struct tm *time_dup;
219
220         if (notification == NULL || time == NULL)
221         {
222                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
223                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
224         }
225
226         if (notification->posted == true)
227         {
228                 LOGE("[%s] ALREADY_POSTED(0x%08x) : unable to change the notification", __FUNCTION__, UI_NOTIFICATION_ERROR_ALREADY_POSTED);
229                 return UI_NOTIFICATION_ERROR_ALREADY_POSTED;
230         }
231
232         time_dup = malloc(sizeof(struct tm));
233
234         if (time_dup == NULL)
235         {
236                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
237                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
238         }
239
240         memcpy(time_dup, time, sizeof(struct tm));
241
242         if (notification->time != NULL)
243         {
244                 free(notification->time);
245         }
246
247         notification->time = time_dup;
248
249         return UI_NOTIFICATION_ERROR_NONE;
250 }
251
252 int ui_notification_get_time(ui_notification_h notification, struct tm **time)
253 {
254         struct tm *time_dup = NULL;
255
256         if (notification == NULL || time == NULL)
257         {
258                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
259                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
260         }
261
262         if (notification->time != NULL)
263         {
264                 time_dup = malloc(sizeof(struct tm));
265
266                 if (time_dup == NULL)
267                 {
268                         LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
269                         return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
270                 }
271         
272                 memcpy(time_dup, notification->time, sizeof(struct tm));
273         }
274
275         *time = time_dup;
276
277         return UI_NOTIFICATION_ERROR_NONE;
278 }
279
280 int ui_notification_set_title(ui_notification_h notification, const char *title)
281 {
282         char *title_dup;
283
284         if (notification == NULL || title == NULL)
285         {
286                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
287                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
288         }
289
290         if (notification->posted == true)
291         {
292                 LOGE("[%s] ALREADY_POSTED(0x%08x) : unable to change the notification", __FUNCTION__, UI_NOTIFICATION_ERROR_ALREADY_POSTED);
293                 return UI_NOTIFICATION_ERROR_ALREADY_POSTED;
294         }
295
296         title_dup = strdup(title);
297
298         if (title_dup == NULL)
299         {
300                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
301                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
302         }
303
304         if (notification->title != NULL)
305         {
306                 free(notification->title);
307         }
308
309         notification->title = title_dup;
310
311         return UI_NOTIFICATION_ERROR_NONE;
312 }
313
314 int ui_notification_get_title(ui_notification_h notification, char **title)
315 {
316         char *title_dup = NULL;
317
318         if (notification == NULL || title == NULL)
319         {
320                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
321                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
322         }
323
324         if (notification->title != NULL)
325         {
326                 title_dup = strdup(notification->title);
327
328                 if (title_dup == NULL)
329                 {
330                         LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
331                         return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
332                 }
333         }
334
335         *title = title_dup;
336
337         return UI_NOTIFICATION_ERROR_NONE;
338 }
339
340
341 int ui_notification_set_content(ui_notification_h notification, const char *content)
342 {
343         char *content_dup;
344
345         if (notification == NULL || content == NULL)
346         {
347                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
348                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
349         }
350
351         if (notification->posted == true)
352         {
353                 LOGE("[%s] ALREADY_POSTED(0x%08x) : unable to change the notification", __FUNCTION__, UI_NOTIFICATION_ERROR_ALREADY_POSTED);
354                 return UI_NOTIFICATION_ERROR_ALREADY_POSTED;
355         }
356
357         content_dup = strdup(content);
358
359         if (content_dup == NULL)
360         {
361                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
362                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
363         }
364
365         if (notification->content != NULL)
366         {
367                 free(notification->content);
368         }
369
370         notification->content = content_dup;
371
372         return UI_NOTIFICATION_ERROR_NONE;
373 }
374
375 int ui_notification_get_content(ui_notification_h notification, char **content)
376 {
377         char *content_dup = NULL;
378
379         if (notification == NULL || content == NULL)
380         {
381                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
382                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
383         }
384
385         if (notification->content != NULL)
386         {
387                 content_dup = strdup(notification->content);
388
389                 if (content_dup == NULL)
390                 {
391                         LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
392                         return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
393                 }
394         }
395
396         *content = content_dup;
397
398         return UI_NOTIFICATION_ERROR_NONE;
399 }
400
401
402 int ui_notification_set_service(ui_notification_h notification, service_h service)
403 {
404         int retcode;
405         service_h service_dup;
406
407         if (notification == NULL || service == NULL)
408         {
409                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
410                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
411         }
412
413         if (notification->posted == true)
414         {
415                 LOGE("[%s] ALREADY_POSTED(0x%08x) : unable to change the notification", __FUNCTION__, UI_NOTIFICATION_ERROR_ALREADY_POSTED);
416                 return UI_NOTIFICATION_ERROR_ALREADY_POSTED;
417         }
418
419         retcode = service_clone(&service_dup, service);
420
421         if (retcode != SERVICE_ERROR_NONE)
422         {
423                 if (retcode == SERVICE_ERROR_OUT_OF_MEMORY)
424                 {
425                         LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
426                         return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
427                 }
428                 else
429                 {
430                         LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid service handle", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
431                         return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
432                 }
433         }
434
435         if (notification->service != NULL)
436         {
437                 service_destroy(notification->service);
438         }
439
440         notification->service = service_dup;
441
442         return UI_NOTIFICATION_ERROR_NONE;
443 }
444
445 int ui_notification_get_service(ui_notification_h notification, service_h *service)
446 {
447         int retcode;
448         service_h service_dup = NULL;
449
450         if (notification == NULL || service == NULL)
451         {
452                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
453                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
454         }
455
456         if (notification->service != NULL)
457         {
458                 retcode = service_clone(&service_dup, notification->service);
459
460                 if (retcode != SERVICE_ERROR_NONE)
461                 {
462                         if (retcode == SERVICE_ERROR_OUT_OF_MEMORY)
463                         {
464                                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
465                                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
466                         }
467                         else
468                         {
469                                 LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid service handle", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
470                                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
471                         }
472                 }
473         }
474
475         *service = service_dup;
476
477         return UI_NOTIFICATION_ERROR_NONE;
478 }
479
480
481 int ui_notification_post(ui_notification_h notification)
482 {
483         int retcode;
484         notification_h core;
485         bundle *service_data;
486
487         if (notification == NULL)
488         {
489                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
490                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
491         }
492
493         if (notification->posted == true)
494         {
495                 LOGE("[%s] ALREADY_POSTED(0x%08x) : unable to change the notification", __FUNCTION__, UI_NOTIFICATION_ERROR_ALREADY_POSTED);
496                 return UI_NOTIFICATION_ERROR_ALREADY_POSTED;
497         }
498
499         // STEP 1: core handle
500         if (notification->ongoing == true)
501         {
502                 core = notification_new(NOTIFICATION_TYPE_ONGOING, NOTIFICATION_GROUP_ID_DEFAULT, NOTIFICATION_PRIV_ID_NONE);
503         }
504         else
505         {
506                 core = notification_new(NOTIFICATION_TYPE_NOTI, NOTIFICATION_GROUP_ID_DEFAULT, NOTIFICATION_PRIV_ID_NONE);
507         }
508
509         if (core == NULL)
510         {
511                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_OUT_OF_MEMORY);
512                 return UI_NOTIFICATION_ERROR_OUT_OF_MEMORY;
513         }
514
515         notification->core = core;
516
517         // STEP 2: icon
518         if (notification->icon != NULL)
519         {
520                 struct stat st;
521         
522                 if (stat(notification->icon, &st) < 0)
523                 {
524                         LOGE("[%s] NO_SUCH_FILE(0x%08x) : invalid icon", __FUNCTION__, UI_NOTIFICATION_ERROR_NO_SUCH_FILE);
525                         return UI_NOTIFICATION_ERROR_NO_SUCH_FILE;
526                 }
527
528                 notification_set_image(core, NOTIFICATION_IMAGE_TYPE_ICON, notification->icon);
529         }
530
531         // STEP 3: time
532         if (notification->time != NULL)
533         {
534                 notification_set_time(core, mktime(notification->time));
535         }
536
537         // STEP 4: title
538         if (notification->title != NULL)
539         {
540                 notification_set_text(core, NOTIFICATION_TEXT_TYPE_TITLE, notification->title, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
541         }
542
543         // STEP 5: content
544         if (notification->content != NULL)
545         {
546                 notification_set_text(core, NOTIFICATION_TEXT_TYPE_CONTENT, notification->content, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
547         }
548
549         // STEP 6: service
550         if (notification->service != NULL && service_to_bundle(notification->service, &service_data) == SERVICE_ERROR_NONE)
551         {
552                 notification_set_execute_option(core, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data);
553         }
554         else
555         {
556                 notification_set_property(core, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
557         }
558
559         // STEP 7: insert
560         retcode = ui_notification_error_handler(notification_insert(core, NULL), __FUNCTION__, "failed to post a notification");
561
562         if (retcode == UI_NOTIFICATION_ERROR_NONE)
563         {
564                 notification->posted = true;
565         }
566
567         return retcode;
568 }
569
570 int ui_notification_update_progress(ui_notification_h notification, ui_notification_progress_type_e type, double value)
571 {
572         int retcode;
573
574         if (notification == NULL)
575         {
576                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
577                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
578         }
579
580         if (notification->core == NULL || notification->posted == false)
581         {
582                 LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid handle", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
583                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
584         }
585
586         switch (type)
587         {
588         case UI_NOTIFICATION_PROGRESS_TYPE_SIZE:
589                 retcode = ui_notification_error_handler(
590                         notification_update_size(notification->core, NOTIFICATION_PRIV_ID_NONE, value),
591                         __FUNCTION__, "failed to update the progress");
592                 break;
593                 
594         case UI_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE:
595                 retcode = ui_notification_error_handler(
596                         notification_update_progress(notification->core, NOTIFICATION_PRIV_ID_NONE, value),
597                         __FUNCTION__, "failed to update the progress");
598                 break;
599
600         default:
601                 LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid progress type", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
602                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
603         }
604
605         return retcode;
606 }
607
608 int ui_notification_cancel(ui_notification_h notification)
609 {
610         int retcode;
611
612         if (notification == NULL)
613         {
614                 LOGE("[%s] INVALID_PARAMETER(0x%08x)", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
615                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
616         }
617
618         if (notification->core == NULL || notification->posted == false)
619         {
620                 LOGE("[%s] INVALID_PARAMETER(0x%08x) : invalid handle", __FUNCTION__, UI_NOTIFICATION_ERROR_INVALID_PARAMETER);
621                 return UI_NOTIFICATION_ERROR_INVALID_PARAMETER;
622         }
623
624         retcode = ui_notification_error_handler(
625                 notification_delete(notification->core),
626                 __FUNCTION__, "failed to cancel the notification");
627
628         return retcode;
629 }
630
631 int ui_notification_cancel_all(void)
632 {
633         return ui_notification_error_handler(
634                 notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_NONE),
635                 __FUNCTION__, "failed to cancel the notification");
636 }
637