926aa3886999c77bb983d8c628948b115d5edfed
[apps/core/preloaded/lockscreen.git] / src / lock_time.c
1 /*
2  * Copyright (c) 2009-2014 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 #include <appcore-common.h>
18
19 #include <unicode/utypes.h>
20 #include <unicode/putil.h>
21 #include <unicode/uiter.h>
22 #include <unicode/udat.h>
23 #include <unicode/udatpg.h>
24 #include <unicode/ustring.h>
25
26 #include "lockscreen.h"
27 #include "log.h"
28 #include "lock_time.h"
29 #include "property.h"
30 #include "default_lock.h"
31
32 #define TIME_LOCALE_FILE "/opt/etc/localtime"
33 #define TIME_ZONEINFO_PATH      "/usr/share/zoneinfo/"
34 #define TIME_ZONEINFO_PATH_LEN  (strlen(TIME_ZONEINFO_PATH))
35
36 static struct _s_info {
37         int is_initialized;
38         Ecore_Timer *timer;
39         int is_timer_enabled;
40         UDateFormat *formatter_date;
41         UDateFormat *formatter_time;
42         UDateFormat *formatter_ampm;
43         UDateTimePatternGenerator *generator;
44         int timeformat;
45         char *timeregion_format;
46         char *timezone_id;
47         Eina_Bool is_pre_meridiem;
48         int is_roaming;
49
50         int need_sync;
51 } s_info = {
52         .is_initialized = 0,
53         .timer = NULL,
54         .is_timer_enabled = 0,
55         .formatter_date = NULL,
56         .formatter_time = NULL,
57         .formatter_ampm = NULL,
58         .generator = NULL,
59         .timeformat = APPCORE_TIME_FORMAT_24,
60         .timeregion_format = NULL,
61         .timezone_id = NULL,
62         .is_pre_meridiem = EINA_FALSE,
63         .is_roaming = -1,
64
65         .need_sync = 0,
66 };
67
68 static void _timer_add(void);
69
70 static UDateFormat *__util_time_ampm_formatter_get(void *data, const char *timezone_id)
71 {
72         UErrorCode status = U_ZERO_ERROR;
73
74         UChar u_best_pattern[64] = {0,};
75         UDateFormat *formatter = NULL;
76
77         u_uastrcpy(u_best_pattern, "a");
78
79         UChar u_timezone_id[64] = {0,};
80         if (!timezone_id) {
81                 u_uastrncpy(u_timezone_id, s_info.timezone_id, sizeof(u_timezone_id));
82                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
83                                 u_best_pattern, -1, &status);
84         } else {
85                 u_uastrncpy(u_timezone_id, timezone_id, sizeof(u_timezone_id));
86                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
87                                 u_best_pattern, -1, &status);
88         }
89         if (U_FAILURE(status)) {
90                 _E("udat_open() failed");
91                 return NULL;
92         }
93
94         char a_best_pattern[64] = {0,};
95         u_austrcpy(a_best_pattern, u_best_pattern);
96
97         return formatter;
98 }
99
100 static UDateFormat *__util_time_time_formatter_get(void *data, int time_format, const char *timezone_id)
101 {
102         char buf[64] = {0,};
103         UErrorCode status = U_ZERO_ERROR;
104         UChar u_pattern[64] = {0,};
105         UChar u_best_pattern[64] = {0,};
106         int32_t u_best_pattern_capacity;
107         char a_best_pattern[64] = {0,};
108
109         UDateFormat *formatter = NULL;
110
111         retv_if(!s_info.generator, NULL);
112
113         if (time_format == APPCORE_TIME_FORMAT_24) {
114                 snprintf(buf, sizeof(buf)-1, "%s", "HH:mm");
115         } else {
116                 /* set time format 12 */
117                 snprintf(buf, sizeof(buf)-1, "%s", "h:mm");
118         }
119
120         if (!u_uastrncpy(u_pattern, buf, sizeof(u_pattern))) {
121                 _E("u_uastrncpy() is failed.");
122                 return NULL;
123         }
124
125         u_best_pattern_capacity =
126                 (int32_t) (sizeof(u_best_pattern) / sizeof((u_best_pattern)[0]));
127
128         udatpg_getBestPattern(s_info.generator, u_pattern, u_strlen(u_pattern),
129                         u_best_pattern, u_best_pattern_capacity, &status);
130         if (U_FAILURE(status)) {
131                 _E("udatpg_getBestPattern() failed");
132                 return NULL;
133         }
134
135         u_austrcpy(a_best_pattern, u_best_pattern);
136
137         if (a_best_pattern[0] == 'a') {
138                 s_info.is_pre_meridiem = EINA_TRUE;
139         } else {
140                 s_info.is_pre_meridiem = EINA_FALSE;
141         }
142
143         char *saveptr;
144         char *a_best_pattern_fixed = strtok_r(a_best_pattern, "a", &saveptr);
145         a_best_pattern_fixed = strtok_r(a_best_pattern_fixed, " ", &saveptr);
146         if (a_best_pattern_fixed) {
147                 u_uastrcpy(u_best_pattern, a_best_pattern_fixed);
148         }
149
150         UChar u_timezone_id[64] = {0,};
151         if (!timezone_id) {
152                 u_uastrncpy(u_timezone_id, s_info.timezone_id, sizeof(u_timezone_id));
153                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
154                                 u_best_pattern, -1, &status);
155         } else {
156                 u_uastrncpy(u_timezone_id, timezone_id, sizeof(u_timezone_id));
157                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
158                                 u_best_pattern, -1, &status);
159         }
160         if (U_FAILURE(status)) {
161                 _E("udat_open() failed");
162                 return NULL;
163         }
164
165         return formatter;
166 }
167
168 static UDateFormat *__util_time_date_formatter_get(void *data, const char *timezone_id, const char *skeleton)
169 {
170         UErrorCode status = U_ZERO_ERROR;
171
172         UChar u_skeleton[64] = {0,};
173         int skeleton_len = 0;
174
175         UChar u_best_pattern[64] = {0,};
176         int32_t u_best_pattern_capacity;
177         UDateFormat *formatter = NULL;
178
179         retv_if(!s_info.generator, NULL);
180
181         u_uastrncpy(u_skeleton, skeleton, strlen(skeleton));
182         skeleton_len = u_strlen(u_skeleton);
183
184         u_best_pattern_capacity =
185                 (int32_t) (sizeof(u_best_pattern) / sizeof((u_best_pattern)[0]));
186
187         udatpg_getBestPattern(s_info.generator, u_skeleton, skeleton_len,
188                         u_best_pattern, u_best_pattern_capacity, &status);
189         if (U_FAILURE(status)) {
190                 _E("udatpg_getBestPattern() failed");
191                 return NULL;
192         }
193
194         UChar u_timezone_id[64] = {0,};
195         if (!timezone_id) {
196                 u_uastrncpy(u_timezone_id, s_info.timezone_id, sizeof(u_timezone_id));
197                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
198                                 u_best_pattern, -1, &status);
199         } else {
200                 u_uastrncpy(u_timezone_id, timezone_id, sizeof(u_timezone_id));
201                 formatter = udat_open(UDAT_IGNORE, UDAT_IGNORE, s_info.timeregion_format, u_timezone_id, -1,
202                                 u_best_pattern, -1, &status);
203         }
204         if (U_FAILURE(status)) {
205                 _E("udat_open() failed");
206                 return NULL;
207         }
208
209         char a_best_pattern[64] = {0,};
210         u_austrcpy(a_best_pattern, u_best_pattern);
211
212         return formatter;
213 }
214
215 static int __util_time_formatted_time_get(UDateFormat *formatter, time_t tt, char *buf, int buf_len)
216 {
217         retv_if (!formatter, -1);
218
219         UDate u_time = (UDate)tt * 1000;
220         UChar u_formatted_str[64] = {0,};
221         int32_t u_formatted_str_capacity;
222         UErrorCode status = U_ZERO_ERROR;
223
224         u_formatted_str_capacity = (int32_t)(sizeof(u_formatted_str) / sizeof((u_formatted_str)[0]));
225
226         (void)udat_format(formatter, u_time, u_formatted_str, u_formatted_str_capacity, NULL, &status);
227         if (U_FAILURE(status)) {
228                 _E("udat_format() failed");
229                 return -1;
230         }
231
232         u_austrncpy(buf, u_formatted_str, buf_len-1);
233         _D("time(%d) formatted(%s)", tt, buf);
234
235         return (int)u_strlen(u_formatted_str);
236 }
237
238 static void _util_time_get(int is_current_time, time_t tt_a, char *timezone, char *skeleton, char **str_date, char **str_time, char **str_meridiem)
239 {
240         time_t tt;
241         struct tm st;
242         char buf_date[512] = {0,};
243         char buf_time[512] = {0,};
244         char buf_ampm[512] = {0,};
245
246         if (is_current_time == 1) {
247                 tt = time(NULL);
248         } else {
249                 tt = tt_a;
250         }
251         localtime_r(&tt, &st);
252
253         UDateFormat *formatter_date = NULL;
254         UDateFormat *formatter_time = NULL;
255         UDateFormat *formatter_ampm = NULL;
256
257         if (timezone != NULL) {
258                 if (!skeleton) {
259                         formatter_date = __util_time_date_formatter_get(NULL, timezone, "MMMMEd");
260                 } else {
261                         formatter_date = __util_time_date_formatter_get(NULL, timezone, skeleton);
262                 }
263                 formatter_time = __util_time_time_formatter_get(NULL, s_info.timeformat, timezone);
264                 if (s_info.timeformat == APPCORE_TIME_FORMAT_12) {
265                         formatter_ampm = __util_time_ampm_formatter_get(NULL, timezone);
266                 }
267         } else {
268                 if (!skeleton) {
269                         formatter_date = s_info.formatter_date;
270                 } else {
271                         formatter_date = __util_time_date_formatter_get(NULL, timezone, skeleton);
272                 }
273                 formatter_time = s_info.formatter_time;
274                 formatter_ampm = s_info.formatter_ampm;
275         }
276
277         if (!s_info.formatter_time) {
278                 s_info.formatter_time = __util_time_time_formatter_get(NULL, s_info.timeformat, NULL);
279         }
280
281         __util_time_formatted_time_get(formatter_date, tt, buf_date, sizeof(buf_date));
282
283         /* time */
284         if (s_info.timeformat == APPCORE_TIME_FORMAT_24) {
285                 __util_time_formatted_time_get(formatter_time, tt, buf_time, sizeof(buf_time)-1);
286         } else {
287                 __util_time_formatted_time_get(formatter_time, tt, buf_time, sizeof(buf_time)-1);
288                 int ampm_len = __util_time_formatted_time_get(formatter_ampm, tt, buf_ampm, sizeof(buf_ampm)-1);
289                 if (ampm_len > 4) {
290                         if (st.tm_hour >= 0 && st.tm_hour < 12) {
291                                 snprintf(buf_ampm, sizeof(buf_ampm)-1, "AM");
292                         } else {
293                                 snprintf(buf_ampm, sizeof(buf_ampm)-1, "PM");
294                         }
295                 }
296         }
297
298         if (str_date != NULL) {
299                 *str_date = strdup(buf_date);
300         }
301
302         if (str_time != NULL) {
303                 *str_time = strdup(buf_time);
304         }
305
306         if (str_meridiem != NULL) {
307                 *str_meridiem = strdup(buf_ampm);
308         }
309
310         if (timezone != NULL) {
311                 if (formatter_date != NULL) udat_close(formatter_date);
312                 if (formatter_time != NULL) udat_close(formatter_time);
313                 if (formatter_ampm != NULL) udat_close(formatter_ampm);
314         }
315 }
316
317 static char *_get_locale(void)
318 {
319         return strdup("en_US.UTF-8");
320 }
321
322 static int _is_korea_locale()
323 {
324         int ret = 0;
325         char *locale = _get_locale();
326         if (locale) {
327                 if (strstr(locale,"ko_KR")) {
328                         ret = 1;
329                 }
330                 free(locale);
331         }
332
333         return ret;
334 }
335
336 lock_error_e lock_time_update(void)
337 {
338         Evas_Object *swipe_layout = NULL;
339
340         struct tm st;
341         time_t tt = time(NULL);
342         localtime_r(&tt, &st);
343
344         char *str_date = NULL;
345         char *str_time = NULL;
346         char *str_meridiem = NULL;
347         char time_buf[PATH_MAX] = {0,};
348         char date_buf[PATH_MAX] = {0,};
349
350         swipe_layout = lock_default_swipe_layout_get();
351         retv_if(!swipe_layout, LOCK_ERROR_FAIL);
352
353         _util_time_get(1, 0, NULL, "MMMMEd", &str_date, &str_time, &str_meridiem);
354         if (s_info.timeformat == APPCORE_TIME_FORMAT_12) {
355                 if (_is_korea_locale()) {
356                         snprintf(time_buf, sizeof(time_buf), "<%s>%s </>%s", "small_font", str_meridiem, str_time);
357                 } else {
358                         snprintf(time_buf, sizeof(time_buf), "%s<%s> %s</>", str_time, "small_font", str_meridiem);
359                 }
360         } else {
361                 if (_is_korea_locale()) {
362                         snprintf(time_buf, sizeof(time_buf), "%s", str_time);
363                 } else {
364                         snprintf(time_buf, sizeof(time_buf), "%s", str_time);
365                 }
366         }
367
368         snprintf(date_buf, sizeof(time_buf), "<%s>%s</>", "small_font", str_date);
369
370         elm_object_part_text_set(swipe_layout, "txt.time", time_buf);
371         elm_object_part_text_set(swipe_layout, "txt.date", str_date);
372
373         free(str_date);
374         free(str_time);
375         free(str_meridiem);
376
377         return LOCK_ERROR_OK;
378 }
379
380 static UDateTimePatternGenerator *__util_time_generator_get(void *data)
381 {
382         UErrorCode status = U_ZERO_ERROR;
383         UDateTimePatternGenerator *generator = NULL;
384
385         retv_if(!s_info.timeregion_format, NULL);
386
387         generator = udatpg_open(s_info.timeregion_format, &status);
388         if (U_FAILURE(status)) {
389                 _E("udatpg_open() failed");
390                 generator = NULL;
391                 return NULL;
392         }
393         return generator;
394 }
395
396 static void _util_time_formatters_create(void *data)
397 {
398         if (!s_info.generator) {
399                 s_info.generator = __util_time_generator_get(NULL);
400         }
401
402         if (!s_info.formatter_date) {
403                 s_info.formatter_date = __util_time_date_formatter_get(NULL, NULL, "MMMMEd");
404         }
405
406         if (s_info.timeformat == APPCORE_TIME_FORMAT_12) {
407                 if (!s_info.formatter_ampm) {
408                         s_info.formatter_ampm = __util_time_ampm_formatter_get(NULL, NULL);
409                 }
410         }
411
412         if (!s_info.formatter_time) {
413                 s_info.formatter_time = __util_time_time_formatter_get(NULL, s_info.timeformat, NULL);
414         }
415 }
416
417 static char *_util_time_timezone_id_get(void)
418 {
419         char tz[1024] = {0,};
420         char *timezone = NULL;
421
422         memcpy(tz, "Asia/Seoul",strlen("Asia/Seoul"));
423         timezone = strdup(tz);
424
425         _D("timezone is %s ", timezone);
426         return timezone;
427 }
428
429 static char *_util_time_regionformat_get(void)
430 {
431         return strdup("en_US");
432 }
433
434 static void _formatter_create(void)
435 {
436         bool timeformat_24_bool = false;
437
438         timeformat_24_bool = true;
439
440         if (timeformat_24_bool) {
441                 _D("TIMEFORMAT : 24");
442                 s_info.timeformat = APPCORE_TIME_FORMAT_24;
443         } else {
444                 _D("TIMEFORMAT : 12");
445                 s_info.timeformat = APPCORE_TIME_FORMAT_12;
446         }
447
448         if (!s_info.timeregion_format) {
449                 s_info.timeregion_format = _util_time_regionformat_get();
450         }
451
452         if (!s_info.timezone_id) {
453                 s_info.timezone_id = _util_time_timezone_id_get();
454         }
455
456         _util_time_formatters_create(NULL);
457
458         s_info.is_initialized = 1;
459         _D("%d %s %s", s_info.timeformat, s_info.timeregion_format, s_info.timezone_id);
460 }
461
462 static void _util_time_formatters_destroy(void)
463 {
464         if (s_info.generator) {
465                 udat_close(s_info.generator);
466                 s_info.generator = NULL;
467         }
468         if (s_info.formatter_date) {
469                 udat_close(s_info.formatter_date);
470                 s_info.formatter_date = NULL;
471         }
472         if (s_info.formatter_time) {
473                 udat_close(s_info.formatter_time);
474                 s_info.formatter_time = NULL;
475         }
476         if (s_info.formatter_ampm) {
477                 udat_close(s_info.formatter_ampm);
478                 s_info.formatter_ampm = NULL;
479         }
480 }
481
482 static void _formatter_destroy(void)
483 {
484         if (s_info.timeregion_format) {
485                 free(s_info.timeregion_format);
486                 s_info.timeregion_format = NULL;
487         }
488         if (s_info.timezone_id) {
489                 free(s_info.timezone_id);
490                 s_info.timezone_id = NULL;
491         }
492
493         _util_time_formatters_destroy();
494
495         s_info.is_initialized = 0;
496 }
497
498 static void _util_time_vconf_changed_cb(keynode_t *key, void *data)
499 {
500         int index = (int)data;
501
502         _formatter_destroy();
503         _formatter_create();
504
505         if (index == 1) {
506                 s_info.need_sync = 1;
507         }
508 }
509
510 static void _time_event_attach(void)
511 {
512         int ret = 0;
513
514         /* register vconf cbs */
515         ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVC_ROAM, _util_time_vconf_changed_cb, (void*)3);
516         ret_if(ret != 0);
517         ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, _util_time_vconf_changed_cb, (void*)4);
518         ret_if(ret != 0);
519 }
520
521 static void _time_event_deattach(void)
522 {
523         int ret = 0;
524
525         /* unregister vconf cbs */
526         ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVC_ROAM, _util_time_vconf_changed_cb);
527         ret_if(ret != 0);
528         ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_INT, _util_time_vconf_changed_cb);
529         ret_if(ret != 0);
530 }
531
532 static Eina_Bool _timer_cb(void *data)
533 {
534         s_info.timer = NULL;
535
536         if (LOCK_ERROR_OK != lock_time_update()) {
537                 _E("Failed to update time & date");
538         }
539
540         if (s_info.is_timer_enabled == 1) {
541                 _timer_add();
542         }
543         return ECORE_CALLBACK_CANCEL;
544 }
545
546 static void _timer_add(void)
547 {
548         time_t tt;
549         struct tm st;
550
551         tt = time(NULL);
552         localtime_r(&tt, &st);
553
554         s_info.timer = ecore_timer_add(60 - st.tm_sec, _timer_cb, NULL);
555 }
556
557 static void _timer_del(void)
558 {
559         if (s_info.timer != NULL) {
560                 ecore_timer_del(s_info.timer);
561                 s_info.timer = NULL;
562         }
563 }
564
565 void lock_time_timer_enable_set(int is_enable)
566 {
567         _timer_del();
568         s_info.is_timer_enabled = is_enable;
569
570         if (is_enable == 1) {
571                 _timer_add();
572         }
573 }
574
575 static void _util_time_reset_view(void)
576 {
577         Evas_Object *swipe_layout = lock_default_swipe_layout_get();
578         ret_if(!swipe_layout);
579
580         elm_object_part_text_set(swipe_layout, "txt.time", "");
581         elm_object_part_text_set(swipe_layout, "txt.date", "");
582 }
583
584 char *lock_time_formatted_noti_time_get(time_t ts)
585 {
586         char *time_str = NULL;
587         char *curr_date = NULL;
588         char *noti_date = NULL;
589
590         _util_time_get(0, time(NULL), NULL, UDAT_YEAR_NUM_MONTH_DAY, &curr_date, NULL, NULL);
591         _util_time_get(0, ts, NULL, UDAT_YEAR_NUM_MONTH_DAY, &noti_date, NULL, NULL);
592
593         if (curr_date != NULL && noti_date != NULL) {
594                 if (strcmp(curr_date, noti_date)) {
595                         char *date = NULL;
596                         _util_time_get(0, ts, NULL, UDAT_ABBR_MONTH_DAY, &date, NULL, NULL);
597                         free(curr_date);
598                         free(noti_date);
599                         return date;
600                 }
601         }
602
603         if (s_info.timeformat == APPCORE_TIME_FORMAT_24) {
604                 _util_time_get(0, ts, NULL, UDAT_HOUR_MINUTE , NULL, &time_str, NULL);
605                 if (time_str) {
606                         return time_str;
607                 }
608         } else {
609                 struct tm st;
610                 localtime_r(&ts, &st);
611                 _util_time_get(0, ts, NULL, UDAT_HOUR_MINUTE , NULL, &time_str, NULL);
612
613                 char buf_ampm[512] = {0,};
614                 int ampm_len = __util_time_formatted_time_get(s_info.formatter_ampm, ts, buf_ampm, sizeof(buf_ampm) - 1);
615                 if (ampm_len > 4) {
616                         if (st.tm_hour >= 0 && st.tm_hour < 12) {
617                                 snprintf(buf_ampm, sizeof(buf_ampm)-1, "AM");
618                         } else {
619                                 snprintf(buf_ampm, sizeof(buf_ampm)-1, "PM");
620                         }
621                 }
622
623                 char time[PATH_MAX];
624
625                 if (_is_korea_locale()) {
626                         snprintf(time, sizeof(time), "%s %s", buf_ampm, time_str);
627                 } else {
628                         snprintf(time, sizeof(time), "%s %s", time_str, buf_ampm);
629                 }
630
631                 free(time_str);
632
633                 return strdup(time);
634         }
635
636         return NULL;
637 }
638
639 void lock_time_resume(void)
640 {
641         if (s_info.need_sync == 1) {
642                 _formatter_destroy();
643                 _formatter_create();
644                 s_info.need_sync = 0;
645         }
646
647         if (LOCK_ERROR_OK != lock_time_update()) {
648                 _E("Failed to update time & date");
649         }
650
651         lock_time_timer_enable_set(1);
652 }
653
654 void lock_time_pause(void)
655 {
656         _util_time_reset_view();
657         lock_time_timer_enable_set(0);
658 }
659
660 void lock_time_init(void)
661 {
662         _formatter_create();
663         _time_event_attach();
664
665         if (LOCK_ERROR_OK != lock_time_update()) {
666                 _E("Failed to update time & date");
667         }
668
669         lock_time_timer_enable_set(1);
670 }
671
672 void lock_time_fini(void)
673 {
674         _formatter_destroy();
675         _time_event_deattach();
676
677         lock_time_timer_enable_set(0);
678 }