From 2b93e293577233446dc91d88bae7cda2f6c2979a Mon Sep 17 00:00:00 2001 From: Jiwan Kim Date: Thu, 2 Jul 2015 14:01:44 +0900 Subject: [PATCH] Code sync from tizen_2.4 Change-Id: I6efe601d017219a2cbcee850cc597a9088314799 --- CMakeLists.txt | 21 +- {src => include}/common.h | 38 +- {src => include}/time_update.h | 8 +- packaging/tel-plugin-nitz.spec | 15 +- resources/mcctable.xml | 237 +++++++++++ src/citylist.c | 733 --------------------------------- src/citylist.h | 39 -- src/desc-nitz.c | 515 ++++++++++++++++++++++- src/time_update.c | 292 ++++++++++--- 9 files changed, 1027 insertions(+), 871 deletions(-) rename {src => include}/common.h (59%) rename {src => include}/time_update.h (68%) create mode 100644 resources/mcctable.xml delete mode 100644 src/citylist.c delete mode 100644 src/citylist.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8208729..c89fd59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,13 +9,23 @@ SET(INCLUDEDIR "\${prefix}/include") # Set required packages INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED glib-2.0 gio-2.0 tcore vconf deviced) +pkg_check_modules(pkgs REQUIRED + glib-2.0 + tcore + vconf + alarm-service + libxml-2.0 + icu-i18n + capi-system-device +) FOREACH(flag ${pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/) +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/include/ +) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wextra -fvisibility=hidden -fPIC") @@ -26,13 +36,16 @@ ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"NITZ\"") ADD_DEFINITIONS("-DPLUGIN_VERSION=${VERSION}") ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))") +IF (TIZEN_FEATURE_NEED_RESTORED_GMT) + ADD_DEFINITIONS("-DTIZEN_FEATURE_NEED_RESTORED_GMT") +ENDIF (TIZEN_FEATURE_NEED_RESTORED_GMT) + MESSAGE(${CMAKE_C_FLAGS}) MESSAGE(${pkgs_LDFLAGS}) SET(SRCS src/desc-nitz.c src/time_update.c - src/citylist.c ) # library build @@ -43,3 +56,5 @@ SET_TARGET_PROPERTIES(nitz-plugin PROPERTIES PREFIX "" OUTPUT_NAME nitz-plugin) # install INSTALL(TARGETS nitz-plugin LIBRARY DESTINATION ${LIBDIR}/telephony/plugins) + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/resources/mcctable.xml DESTINATION /opt/data/etc PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ) \ No newline at end of file diff --git a/src/common.h b/include/common.h similarity index 59% rename from src/common.h rename to include/common.h index ebab6d6..9ed5cac 100644 --- a/src/common.h +++ b/include/common.h @@ -22,10 +22,17 @@ #include #include #include +#include +#include + +#include +#include + +#ifdef FEATURE_FILE_LOG /* filelog */ #ifndef NITZ_LOG_FILE -#define NITZ_LOG_FILE "/opt/var/log/nitz.log" +#define NITZ_LOG_FILE "/opt/var/log/nitz.log" #endif #ifndef NITZ_LOG_FUNC @@ -42,4 +49,33 @@ } \ } +#else +#define filelog(fmt, args...) warn(fmt, ##args); +#endif + +#define NITZ_TIMEZONE_MAX_LEN 64 + +struct nitz_custom_data { + gboolean nitz_updated; + gboolean need_fix_zone; + gboolean wait_for_icc_card; + gboolean wait_for_net_registration; + + char *plmn; + GHashTable *mcctable_hash; + + GQueue *nitz_pending_queue; + CoreObject *co_network; + TcorePlugin *plugin; +}; + +typedef enum ConnMode { + CONN_MODE_COMPAINION, + CONN_MODE_REMOTE, + CONN_MODE_STANDALONE, + CONN_MODE_UNKNOWN +} ConnMode; + +char * __nitz_get_country_code_for_mcc(char *operator_mcc, struct nitz_custom_data *custom_data); + #endif diff --git a/src/time_update.h b/include/time_update.h similarity index 68% rename from src/time_update.h rename to include/time_update.h index 5c2f758..7ad3246 100644 --- a/src/time_update.h +++ b/include/time_update.h @@ -19,8 +19,10 @@ #ifndef __NITZ_TIME_H__ #define __NITZ_TIME_H__ -int nitz_apply_tzfile(const char *tzfilename, gboolean mode_auto); -long nitz_get_uptime(); -gboolean nitz_time_update(const struct tnoti_network_timeinfo *time_info, gboolean mode_auto); +int nitz_apply_tzfile (const char *tzfilename); +gboolean nitz_is_auto_timezone (void); +gboolean nitz_time_update (const struct tnoti_network_timeinfo *time_info, struct nitz_custom_data *data, gint delay); +GList * nitz_get_tzlist(char *iso, const struct tnoti_network_timeinfo *ti); +gboolean nitz_set_time (time_t tt_gmt_nitz); #endif diff --git a/packaging/tel-plugin-nitz.spec b/packaging/tel-plugin-nitz.spec index ee8a996..030980f 100644 --- a/packaging/tel-plugin-nitz.spec +++ b/packaging/tel-plugin-nitz.spec @@ -1,6 +1,7 @@ %define major 0 %define minor 1 -%define patchlevel 19 +%define patchlevel 70 + Name: tel-plugin-nitz Summary: nitz plugin for telephony Version: %{major}.%{minor}.%{patchlevel} @@ -12,10 +13,12 @@ Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig BuildRequires: cmake BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(icu-i18n) BuildRequires: pkgconfig(tcore) BuildRequires: pkgconfig(vconf) -BuildRequires: pkgconfig(deviced) +BuildRequires: pkgconfig(alarm-service) +BuildRequires: pkgconfig(capi-system-device) %description nitz plugin for telephony @@ -28,7 +31,7 @@ versionint=$[%{major} * 1000000 + %{minor} * 1000 + %{patchlevel}] cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DLIB_INSTALL_DIR=%{_libdir} \ -DVERSION=$versionint -make %{?jobs:-j%jobs} +make %{?_smp_mflags} %post /sbin/ldconfig @@ -41,6 +44,6 @@ rm -rf %{buildroot} %files %manifest tel-plugin-nitz.manifest -%defattr(-,root,root,-) -#%doc COPYING +%defattr(644,system,system,-) %{_libdir}/telephony/plugins/* +/opt/data/etc/mcctable.xml diff --git a/resources/mcctable.xml b/resources/mcctable.xml new file mode 100644 index 0000000..c40d566 --- /dev/null +++ b/resources/mcctable.xml @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/citylist.c b/src/citylist.c deleted file mode 100644 index 76693e3..0000000 --- a/src/citylist.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * tel-plugin-nitz - * - * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include - -#include - -#include "common.h" -#include "citylist.h" - -static NITZ_MCC_TZFILE_MAP nitz_table_mcc_tzfile[] = -{ - { 202, "GR", -1, +2, +1, "Europe/Athens" }, // Greece -- Athens - { 204, "NL", -1, +1, +1, "Europe/Amsterdam" }, // Netherlands -- Amsterdam - { 206, "BE", -1, +1, +1, "Europe/Brussels" }, // Belgium -- Brussels - { 208, "FR", -1, +1, +1, "Europe/Paris" }, // France -- Paris - { 212, "MC", -1, +1, +1, "Europe/Monaco" }, // Monaco -- Monaco - { 213, "AD", -1, +1, +1, "Europe/Andorra" }, // Andorra -- Andorra la Vella - - { 214, "ES", 0, +1, +1, "Europe/Madrid" }, // Spain -- Madrid - { 214, "ES", 1, +1, +1, "Africa/Ceuta" }, // - { 214, "ES", 2, 0, +1, "Atlantic/Canary" }, // - - { 216, "HU", -1, 0, 0, "Europe/Budapest" }, // Hungary -- Budapest - { 218, "BA", -1, 0, 0, "Europe/Sarajevo" }, // Bosnia and Herzegovina -- Sarajevo - { 219, "HR", -1, 0, 0, "Europe/Zagreb" }, // Croatia -- Zagreb - { 220, "RS", -1, 0, 0, "Europe/Belgrade" }, // Serbia -- Belgrade - { 222, "IT", -1, 0, 0, "Europe/Rome" }, // Italy -- Rome - { 225, "VA", -1, 0, 0, "Europe/Vatican" }, - { 226, "RO", -1, 0, 0, "Europe/Bucharest" }, // Romania -- Bucharest - { 228, "CH", -1, 0, 0, "Europe/Zurich" }, // Switzerland -- Bern - { 230, "CZ", -1, 0, 0, "Europe/Prague" }, // Czech Republic -- Prague - { 231, "SK", -1, 0, 0, "Europe/Bratislava" }, // Slovak Republic -- Bratislava - { 232, "AT", -1, 0, 0, "Europe/Vienna" }, // Austria -- Vienna - { 234, "GB", -1, 0, 0, "Europe/London" }, // United Kingdom -- London - { 235, "GB", -1, 0, 0, "Europe/London" }, // United Kingdom -- London - { 238, "DK", -1, 0, 0, "Europe/Copenhagen" }, // Denmark -- Copenhagen - { 240, "SE", -1, 0, 0, "Europe/Stockholm" }, // Sweden -- Stockholm - { 242, "NO", -1, 0, 0, "Europe/Oslo" }, // Norway -- Oslo - { 244, "FI", -1, 0, 0, "Europe/Helsinki" }, // Finland -- Helsinki - { 246, "LT", -1, 0, 0, "Europe/Vilnius" }, // Lithuania -- Vilnius - { 247, "LV", -1, 0, 0, "Europe/Riga" }, // Latvia -- Riga - { 248, "EE", -1, 0, 0, "Europe/Tallinn" }, // Estonia -- Tallinn - - { 250, "RU", 0, +3, +1, "Europe/Moscow" }, // Russia -- Moscow+00 - { 250, "RU", 1, +2, +1, "Europe/Kaliningrad" }, // Russia -- Moscow-01 - { 250, "RU", 2, +3, +1, "Europe/Volgograd" }, // Russia -- Moscow+00 - { 250, "RU", 3, +3, +1, "Europe/Samara" }, // Russia -- Moscow - { 250, "RU", 4, +5, +1, "Asia/Yekaterinburg" }, // Russia -- Moscow+02 - { 250, "RU", 5, +6, +1, "Asia/Omsk" }, // Russia -- Moscow+03 - { 250, "RU", 6, +6, +1, "Asia/Novosibirsk" }, // Russia -- Moscow+03 - { 250, "RU", 7, +6, +1, "Asia/Novokuznetsk" }, // Russia -- Moscow+03 - { 250, "RU", 8, +7, +1, "Asia/Krasnoyarsk" }, // Russia -- Moscow+04 - { 250, "RU", 9, +8, +1, "Asia/Irkutsk" }, // Russia -- Moscow+05 - { 250, "RU", 10, +9, +1, "Asia/Yakutsk" }, // Russia -- Moscow+06 - { 250, "RU", 11, +10, +1, "Asia/Vladivostok" }, // Russia -- Moscow+07 - { 250, "RU", 12, +10, +1, "Asia/Sakhalin" }, // Russia -- Moscow+07 - { 250, "RU", 13, +11, +1, "Asia/Magadan" }, // Russia -- Moscow+08 - { 250, "RU", 14, +11, +1, "Asia/Kamchatka" }, // Russia -- Moscow+08 - { 250, "RU", 15, +11, +1, "Asia/Anadyr" }, // Russia -- Moscow+08 - - { 255, "UA", 0, +2, +1, "Europe/Kiev" }, // Ukraine -- Kiev - { 255, "UA", 1, +2, +1, "Europe/Uzhgorod" }, // Ukraine -- - { 255, "UA", 2, +2, +1, "Europe/Zaporozhye" }, // Ukraine -- - { 255, "UA", 3, +2, +1, "Europe/Simferopol" }, // Ukraine -- - - { 257, "BY", -1, 0, 0, "Europe/Minsk" }, // Belarus Republic -- Minsk - { 259, "MD", -1, 0, 0, "Europe/Chisinau" }, // Moldova -- Kishinev(Chisinau) - { 260, "PL", -1, 0, 0, "Europe/Warsaw" }, // Poland -- Warsaw - { 262, "DE", -1, 0, 0, "Europe/Berlin" }, // Germany -- Berlin - { 266, "GI", -1, 0, 0, "Europe/Gibraltar" }, // Gibraltar -- Gibraltar - - { 268, "PT", 0, +0, +1, "Europe/Lisbon" }, // Portugal -- Lisbon - { 268, "PT", 1, +0, +1, "Atlantic/Madeira" }, // - { 268, "PT", 2, -1, +1, "Atlantic/Azores" }, // - - { 270, "LU", -1, 0, 0, "Europe/Luxembourg" }, // Luxembourg -- Luxembourg - { 272, "IE", -1, 0, 0, "Europe/Dublin" }, // Ireland -- Dublin - { 274, "IS", -1, 0, 0, "Atlantic/Reykjavik" }, // Iceland -- Reykjavik - { 276, "AL", -1, 0, 0, "Europe/Tirane" }, // Albania -- Tirane - { 278, "MT", -1, 0, 0, "Europe/Malta" }, // Malta -- Valletta - { 280, "CY", -1, 0, 0, "Asia/Nicosia" }, // Cyprus -- Nicosia - { 282, "GE", -1, 0, 0, "Asia/Tbilisi" }, // Georgia -- Tbilisi - { 283, "AM", -1, 0, 0, "Asia/Yerevan" }, // Armenia -- Yerevan - { 284, "BG", -1, 0, 0, "Europe/Sofia" }, // Bulgaria -- Sofia - { 286, "TR", -1, 0, 0, "Europe/Istanbul" }, // Turkey -- Ankara - { 288, "FO", -1, 0, 0, "Atlantic/Faroe" }, // Faroe Islands -- Torshavn - - { 290, "GL", 0, -3, +1, "America/Godthab" }, // Greenland -- Nuuk /*!*/ - { 290, "GL", 1, +0, +0, "America/Danmarkshavn" }, // - { 290, "GL", 2, -1, +1, "America/Scoresbysund" }, // - { 290, "GL", 3, -4, +1, "America/Thule" }, // - - { 292, "SM", -1, 0, 0, "Europe/San_Marino" }, // San Marino -- San Marino - { 293, "SI", -1, 0, 0, "Europe/Ljubljana" }, // Slovenia -- Ljubljana - { 294, "MK", -1, 0, 0, "Europe/Skopje" }, // Macedonia -- Skopje - { 295, "LI", -1, 0, 0, "Europe/Vaduz" }, // Liechtenstein -- Vaduz - { 297, "ME", -1, 0, 0, "Europe/Podgorica" }, // Montenegro -- Podgorica - - { 302, "CA", 0, -4, +1, "America/St_Johns" }, // - { 302, "CA", 1, -4, +1, "America/Halifax" }, // - { 302, "CA", 2, -4, +1, "America/Glace_Bay" }, // - { 302, "CA", 3, -4, +1, "America/Moncton" }, // - { 302, "CA", 4, -4, +1, "America/Goose_Bay" }, // - { 302, "CA", 5, -4, +0, "America/Blanc-Sablon" }, // - { 302, "CA", 6, -5, +1, "America/Montreal" }, // - { 302, "CA", 7, -5, +1, "America/Toronto" }, //Canada -- Ottawa /*!*/ - { 302, "CA", 8, -5, +1, "America/Nipigon" }, // - { 302, "CA", 9, -5, +1, "America/Thunder_Bay" }, // - { 302, "CA", 10, -5, +1, "America/Iqaluit" }, // - { 302, "CA", 11, -5, +1, "America/Pangnirtung" }, // - { 302, "CA", 12, -6, +1, "America/Resolute" }, // - { 302, "CA", 13, -6, +1, "America/Atikokan" }, // - { 302, "CA", 14, -6, +1, "America/Rankin_Inlet" }, // - { 302, "CA", 15, -6, +1, "America/Winnipeg" }, // - { 302, "CA", 16, -6, +1, "America/Rainy_River" }, // - { 302, "CA", 17, -6, +0, "America/Regina" }, // - { 302, "CA", 18, -8, +1, "America/Swift_Current" }, // - { 302, "CA", 19, -7, +1, "America/Edmonton" }, // - { 302, "CA", 20, -7, +1, "America/Cambridge_Bay" }, // - { 302, "CA", 21, -7, +1, "America/Yellowknife" }, // - { 302, "CA", 22, -7, +1, "America/Inuvik" }, // - { 302, "CA", 23, -7, +0, "America/Dawson_Creek" }, // - { 302, "CA", 24, -8, +1, "America/Vancouver" }, // - { 302, "CA", 25, -8, +1, "America/Whitehorse" }, // - { 302, "CA", 26, -8, +1, "America/Dawson" }, // - - { 308, "PM", -1, 0, 0, "America/Miquelon" }, // Saint Pierre and Miquelon -- Saint-Pierre - - { 310, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 310, "US", 1, -5, +1, "America/Detroit" }, // - { 310, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 310, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 310, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 310, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 310, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 310, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 310, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 310, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 310, "US", 10, -6, +1, "America/Chicago" }, // - { 310, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 310, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 310, "US", 13, -6, +1, "America/Menominee" }, // - { 310, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 310, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 310, "US", 16, -7, +1, "America/Denver" }, // - { 310, "US", 17, -7, +1, "America/Boise" }, // - { 310, "US", 18, -7, +1, "America/Shiprock" }, // - { 310, "US", 19, -7, +0, "America/Phoenix" }, // - { 310, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 310, "US", 21, -9, +1, "America/Anchorage" }, // = Alaska - { 310, "US", 22, -9, +1, "America/Juneau" }, // - { 310, "US", 23, -9, +1, "America/Yakutat" }, // - { 310, "US", 24, -9, +1, "America/Nome" }, // - { 310, "US", 25, -10, +1, "America/Adak" }, // - { 310, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 311, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 311, "US", 1, -5, +1, "America/Detroit" }, // - { 311, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 311, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 311, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 311, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 311, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 311, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 311, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 311, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 311, "US", 10, -6, +1, "America/Chicago" }, // - { 311, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 311, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 311, "US", 13, -6, +1, "America/Menominee" }, // - { 311, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 311, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 311, "US", 16, -7, +1, "America/Denver" }, // - { 311, "US", 17, -7, +1, "America/Boise" }, // - { 311, "US", 18, -7, +1, "America/Shiprock" }, // - { 311, "US", 19, -7, +0, "America/Phoenix" }, // - { 311, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 311, "US", 21, -9, +1, "America/Anchorage" }, // - { 311, "US", 22, -9, +1, "America/Juneau" }, // - { 311, "US", 23, -9, +1, "America/Yakutat" }, // - { 311, "US", 24, -9, +1, "America/Nome" }, // - { 311, "US", 25, -10, +1, "America/Adak" }, // - { 311, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 312, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 312, "US", 1, -5, +1, "America/Detroit" }, // - { 312, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 312, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 312, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 312, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 312, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 312, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 312, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 312, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 312, "US", 10, -6, +1, "America/Chicago" }, // - { 312, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 312, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 312, "US", 13, -6, +1, "America/Menominee" }, // - { 312, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 312, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 312, "US", 16, -7, +1, "America/Denver" }, // - { 312, "US", 17, -7, +1, "America/Boise" }, // - { 312, "US", 18, -7, +1, "America/Shiprock" }, // - { 312, "US", 19, -7, +0, "America/Phoenix" }, // - { 312, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 312, "US", 21, -9, +1, "America/Anchorage" }, // - { 312, "US", 22, -9, +1, "America/Juneau" }, // - { 312, "US", 23, -9, +1, "America/Yakutat" }, // - { 312, "US", 24, -9, +1, "America/Nome" }, // - { 312, "US", 25, -10, +1, "America/Adak" }, // - { 312, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 313, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 313, "US", 1, -5, +1, "America/Detroit" }, // - { 313, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 313, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 313, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 313, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 313, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 313, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 313, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 313, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 313, "US", 10, -6, +1, "America/Chicago" }, // - { 313, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 313, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 313, "US", 13, -6, +1, "America/Menominee" }, // - { 313, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 313, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 313, "US", 16, -7, +1, "America/Denver" }, // - { 313, "US", 17, -7, +1, "America/Boise" }, // - { 313, "US", 18, -7, +1, "America/Shiprock" }, // - { 313, "US", 19, -7, +0, "America/Phoenix" }, // - { 313, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 313, "US", 21, -9, +1, "America/Anchorage" }, // - { 313, "US", 22, -9, +1, "America/Juneau" }, // - { 313, "US", 23, -9, +1, "America/Yakutat" }, // - { 313, "US", 24, -9, +1, "America/Nome" }, // - { 313, "US", 25, -10, +1, "America/Adak" }, // - { 313, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 314, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 314, "US", 1, -5, +1, "America/Detroit" }, // - { 314, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 314, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 314, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 314, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 314, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 314, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 314, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 314, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 314, "US", 10, -6, +1, "America/Chicago" }, // - { 314, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 314, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 314, "US", 13, -6, +1, "America/Menominee" }, // - { 314, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 314, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 314, "US", 16, -7, +1, "America/Denver" }, // - { 314, "US", 17, -7, +1, "America/Boise" }, // - { 314, "US", 18, -7, +1, "America/Shiprock" }, // - { 314, "US", 19, -7, +0, "America/Phoenix" }, // - { 314, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 314, "US", 21, -9, +1, "America/Anchorage" }, // - { 314, "US", 22, -9, +1, "America/Juneau" }, // - { 314, "US", 23, -9, +1, "America/Yakutat" }, // - { 314, "US", 24, -9, +1, "America/Nome" }, // - { 314, "US", 25, -10, +1, "America/Adak" }, // - { 314, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 315, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 315, "US", 1, -5, +1, "America/Detroit" }, // - { 315, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 315, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 315, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 315, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 315, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 315, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 315, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 315, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 315, "US", 10, -6, +1, "America/Chicago" }, // - { 315, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 315, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 315, "US", 13, -6, +1, "America/Menominee" }, // - { 315, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 315, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 315, "US", 16, -7, +1, "America/Denver" }, // - { 315, "US", 17, -7, +1, "America/Boise" }, // - { 315, "US", 18, -7, +1, "America/Shiprock" }, // - { 315, "US", 19, -7, +0, "America/Phoenix" }, // - { 315, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 315, "US", 21, -9, +1, "America/Anchorage" }, // - { 315, "US", 22, -9, +1, "America/Juneau" }, // - { 315, "US", 23, -9, +1, "America/Yakutat" }, // - { 315, "US", 24, -9, +1, "America/Nome" }, // - { 315, "US", 25, -10, +1, "America/Adak" }, // - { 315, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 316, "US", 0, -5, +1, "America/New_York" }, // U.S.A /*!*/ - { 316, "US", 1, -5, +1, "America/Detroit" }, // - { 316, "US", 2, -5, +1, "America/Kentucky/Louisville" }, // - { 316, "US", 3, -5, +1, "America/Kentucky/Monticello" }, // - { 316, "US", 4, -5, +1, "America/Indiana/Indianapolis" }, // - { 316, "US", 5, -5, +1, "America/Indiana/Vincennes" }, // - { 316, "US", 6, -5, +1, "America/Indiana/Winamac" }, // - { 316, "US", 7, -5, +1, "America/Indiana/Marengo" }, // - { 316, "US", 8, -5, +1, "America/Indiana/Petersburg" }, // - { 316, "US", 9, -5, +1, "America/Indiana/Vevay" }, // - { 316, "US", 10, -6, +1, "America/Chicago" }, // - { 316, "US", 11, -6, +1, "America/Indiana/Tell_City" }, // - { 316, "US", 12, -6, +1, "America/Indiana/Knox" }, // - { 316, "US", 13, -6, +1, "America/Menominee" }, // - { 316, "US", 14, -6, +1, "America/North_Dakota/Center" }, // - { 316, "US", 15, -6, +1, "America/North_Dakota/New_Salem" }, // - { 316, "US", 16, -7, +1, "America/Denver" }, // - { 316, "US", 17, -7, +1, "America/Boise" }, // - { 316, "US", 18, -7, +1, "America/Shiprock" }, // - { 316, "US", 19, -7, +0, "America/Phoenix" }, // - { 316, "US", 20, -8, +1, "America/Los_Angeles" }, // - { 316, "US", 21, -9, +1, "America/Anchorage" }, // - { 316, "US", 22, -9, +1, "America/Juneau" }, // - { 316, "US", 23, -9, +1, "America/Yakutat" }, // - { 316, "US", 24, -9, +1, "America/Nome" }, // - { 316, "US", 25, -10, +1, "America/Adak" }, // - { 316, "US", 26, -10, +0, "Pacific/Honolulu" }, // - - { 330, "PR", -1, 0, 0, "America/Puerto_Rico" }, // Puerto Rico -- San Juan - { 332, "VI", -1, 0, 0, "America/St_Thomas" }, // United States Virgin Islands -- Charlotte Amalie /*!*/ - - { 334, "MX", 0, -6, +1, "America/Mexico_City" }, // Mexico -- Mexico City - { 334, "MX", 1, -6, +1, "America/Cancun" }, // - { 334, "MX", 2, -6, +1, "America/Merida" }, // - { 334, "MX", 3, -6, +1, "America/Monterrey" }, // - { 334, "MX", 4, -6, +1, "America/Matamoros" }, // - { 334, "MX", 5, -7, +1, "America/Mazatlan" }, // - { 334, "MX", 6, -7, +1, "America/Chihuahua" }, // - { 334, "MX", 7, -6, +1, "America/Ojinaga" }, // - { 334, "MX", 8, -7, +0, "America/Hermosillo" }, // - { 334, "MX", 9, -8, +1, "America/Tijuana" }, // - { 334, "MX", 10, -6, +1, "America/Santa_Isabel" }, // - { 334, "MX", 11, -7, +1, "America/Bahia_Banderas" }, // - - { 338, "JM", -1, 0, 0, "America/Jamaica" }, // Jamaica -- Kingston - { 340, "GP", -1, 0, 0, "America/Guadeloupe" }, // Guadeloupe(france) -- Basse-Terre - { 340, "MQ", -1, 0, 0, "America/Martinique" }, - { 342, "BB", -1, 0, 0, "America/Barbados" }, // Barbados -- Bridgetown - { 344, "AG", -1, 0, 0, "America/Antigua" }, // Antigua & Barbuda -- Saint John's - { 346, "KY", -1, 0, 0, "America/Cayman" }, // Cayman Islands -- George Town - { 348, "VG", -1, 0, 0, "America/Tortola" }, // British Virgin Islands -- Road Town - { 350, "BM", -1, 0, 0, "Atlantic/Bermuda" }, // Bermuda -- Hamilton - { 352, "GD", -1, 0, 0, "America/Grenada" }, // Grenada -- Saint George's - { 354, "MS", -1, 0, 0, "America/Montserrat" }, // Montserrat(UK) -- Plymouth - { 356, "KN", -1, 0, 0, "America/St_Kitts" }, // Saint Kitts and Nevis -- Basseterre - { 358, "LC", -1, 0, 0, "America/St_Lucia" }, // Saint Lucia -- Castries - { 360, "VC", -1, 0, 0, "America/St_Vincent" }, // Saint Vincent and the Grenadines -- Kingstown - { 362, "AN", -1, 0, 0, "America/Curacao" }, // Netherlands Antilles -- Willemstad - { 363, "AW", -1, 0, 0, "America/Aruba" }, // Aruba(netherlands) -- Oranjestad - { 364, "BS", -1, 0, 0, "America/Nassau" }, // Bahamas -- Nassau - { 365, "AI", -1, 0, 0, "America/Antigua" }, // Anguilla -- The Valley - { 366, "DM", -1, 0, 0, "America/Dominica" }, // Dominica -- Roseau - { 368, "CU", -1, 0, 0, "America/Havana" }, // Cuba -- Havana - { 370, "DO", -1, 0, 0, "America/Santo_Domingo" }, // Dominican Republic -- Santo Domingo - { 372, "HT", -1, 0, 0, "America/Port-au-Prince" }, // Haiti -- Port au Prince //world - { 374, "TT", -1, 0, 0, "America/Port_of_Spain" }, // Trinidad and Tobago -- Port of Spain - { 376, "TC", -1, 0, 0, "America/Grand_Turk" }, // Turks & Caicos islands(UK) -- Cockburn Town - { 400, "AZ", -1, 0, 0, "Asia/Baku" }, // Azerbaijan -- Baku - - { 401, "KZ", 0, +6, +0, "Asia/Almaty" }, - { 401, "KZ", 1, +5, +0, "Asia/Qyzylorda" }, - { 401, "KZ", 2, +5, +0, "Asia/Aqtobe" }, - { 401, "KZ", 3, +5, +0, "Asia/Aqtau" }, - { 401, "KZ", 4, +5, +0, "Asia/Oral" }, - - { 402, "BT", -1, 0, 0, "Asia/Thimphu" }, // Bhutan -- Thimphu - { 404, "IN", -1, 0, 0, "Asia/Kolkata" }, // India - New Delhi - { 405, "IN", -1, 0, 0, "Asia/Kolkata" }, // India - New Delhi - { 410, "PK", -1, 0, 0, "Asia/Karachi" }, // Pakistan -- Islamabad - { 412, "AF", -1, 0, 0, "Asia/Kabul" }, // Afghanistan -- Kabul - { 413, "LK", -1, 0, 0, "Asia/Colombo" }, // Sri Lanka -- Colombo - { 414, "MM", -1, 0, 0, "Asia/Rangoon" }, // Myanmar -- Rangoon (Yangon) - { 415, "LB", -1, 0, 0, "Asia/Beirut" }, // Lebanon -- Beirut - { 416, "JO", -1, 0, 0, "Asia/Amman" }, // Jordan -- Amman - { 417, "SY", -1, 0, 0, "Asia/Damascus" }, // Syria -- Damascus - { 418, "IQ", -1, 0, 0, "Asia/Baghdad" }, // Iraq -- Baghdad - { 419, "KW", -1, 0, 0, "Asia/Kuwait" }, // Kuwait -- Kuwait City - { 420, "SA", -1, 0, 0, "Asia/Riyadh" }, // Saudi Arabia -- Riyadh - { 421, "YE", -1, 0, 0, "Asia/Aden" }, // Yemen -- Sanaa /*!*/ - { 422, "OM", -1, 0, 0, "Asia/Muscat" }, // Oman -- Muscat - { 423, "PS", -1, 0, 0, "Asia/Gaza" }, - { 424, "AE", -1, 0, 0, "Asia/Dubai" }, // United Arab Emirates -- Abu Dhabi /*!*/ - { 425, "IL", -1, 0, 0, "Asia/Jerusalem" }, // Israel -- Tel Aviv /*!*/ - { 426, "BH", -1, 0, 0, "Asia/Bahrain" }, // Bahrain -- Manama - { 427, "QA", -1, 0, 0, "Asia/Qatar" }, // Qatar -- Doha - - { 428, "MN", 0, +8, +0, "Asia/Ulaanbaatar" }, // Mongolia -- Ulaanbaatar - { 428, "MN", 1, +7, +0, "Asia/Hovd" }, // - { 428, "MN", 2, +8, +0, "Asia/Choibalsan" }, // - - { 429, "NP", -1, 0, 0, "Asia/Kathmandu" }, // Nepal -- Kathmandu - { 430, "AE", -1, 0, 0, "Asia/Dubai" }, // Abu Dhabi - { 431, "AE", -1, 0, 0, "Asia/Dubai" }, // Dubai - { 432, "IR", -1, 0, 0, "Asia/Tehran" }, // Iran -- Tehran - - { 434, "UZ", 0, +5, +0, "Asia/Samarkand" }, // Uzbekistan -- Samarkand - { 434, "UZ", 1, +5, +0, "Asia/Tashkent" }, // Uzbekistan -- Tashkent - - { 436, "TJ", -1, 0, 0, "Asia/Dushanbe" }, // Tajikistan -- Dushanbe - { 437, "KG", -1, 0, 0, "Asia/Bishkek" }, // Kyrgyzstan -- Bishkek - { 438, "TM", -1, 0, 0, "Asia/Ashgabat" }, // Turkmenistan -- Ashgabat - { 440, "JP", -1, 0, 0, "Asia/Tokyo" }, // Japan -- Tokyo - { 441, "JP", -1, 0, 0, "Asia/Tokyo" }, - { 450, "KR", -1, 0, 0, "Asia/Seoul" }, // South Korea -- Seoul - { 452, "VN", -1, 0, 0, "Asia/Ho_Chi_Minh" }, // Vietnam -- Hanoi - { 454, "HK", -1, 0, 0, "Asia/Hong_Kong" }, // Hong Kong - Hong Kong - { 455, "MO", -1, 0, 0, "Asia/Macau" }, // Macau(PRC) -- ??? - { 456, "KH", -1, 0, 0, "Asia/Phnom_Penh" }, // Cambodia -- Phnom Penh - { 457, "LA", -1, 0, 0, "Asia/Vientiane" }, // Laos -- Vientiane - - { 460, "CN", 0, +8, +0, "Asia/Shanghai" }, // China -- Beijing /*!*/ - { 460, "CN", 1, +8, +0, "Asia/Harbin" }, // - { 460, "CN", 2, +8, +0, "Asia/Chongqing" }, // - { 460, "CN", 3, +8, +0, "Asia/Urumqi" }, // - { 460, "CN", 4, +8, +0, "Asia/Kashgar" }, // - - { 466, "TW", -1, 0, 0, "Asia/Taipei" }, // Taiwan -- Taipei - { 467, "KP", -1, 0, 0, "Asia/Pyongyang" }, // North Korea -- Pyongyang - { 470, "BD", -1, 0, 0, "Asia/Dhaka" }, // Bangladesh -- Dhaka - { 472, "MV", -1, 0, 0, "Indian/Maldives" }, // Maldives -- Male - - { 502, "MY", 0, +8, +0, "Asia/Kuala_Lumpur" },// Malaysia -- Kuala Lumpur - { 502, "MY", 1, +8, +0, "Asia/Kuching" }, // - - { 505, "AU", 0, +10, +1, "Australia/Sydney" }, // Australia -- Canberra (n-project: Sydney) /*!*/ - { 505, "AU", 1, +10, +1, "Australia/Lord_Howe" }, // +10:30, +00:30 /*!*/ - { 505, "AU", 2, +10, +1, "Australia/Hobart" }, // - { 505, "AU", 3, +10, +1, "Australia/Currie" }, // - { 505, "AU", 4, +10, +1, "Australia/Melbourne" }, // - { 505, "AU", 5, +10, +1, "Australia/Broken_Hill" }, // - { 505, "AU", 6, +10, +0, "Australia/Brisbane" }, // - { 505, "AU", 7, +10, +0, "Australia/Lindeman" }, // - { 505, "AU", 8, +9, +1, "Australia/Adelaide" }, // +09:30, +01:00 - { 505, "AU", 9, +9, +0, "Australia/Darwin" }, // +09:30, +0 - { 505, "AU", 10, +8, +0, "Australia/Perth" }, // - { 505, "AU", 11, +8, +0, "Australia/Eucla" }, // +08:45 - - { 510, "ID", 0, +7, +0, "Asia/Jakarta" }, // Indonesia -- Jakarta - { 510, "ID", 1, +7, +0, "Asia/Pontianak" }, // - { 510, "ID", 2, +8, +0, "Asia/Makassar" }, // - { 510, "ID", 3, +9, +0, "Asia/Jayapura" }, // - - { 514, "TL", -1, 0, 0, "Asia/Dili" }, // Timor -- Dili - { 515, "PH", -1, 0, 0, "Asia/Manila" }, // Philippines -- Manila - { 520, "TH", -1, 0, 0, "Asia/Bangkok" }, // Thailand -- Bangkok - { 525, "SG", -1, 0, 0, "Asia/Singapore" }, // Singapore -- Singapore - { 528, "BN", -1, 0, 0, "Asia/Brunei" }, // Brunei Darussalam -- Bandar Seri Begawan - - { 530, "NZ", 0, +12, +1, "Pacific/Auckland" },// New Zealand -- Wellington /*!*/ - { 530, "NZ", 1, +12, +1, "Pacific/Chatham" }, // +12:45, +01:00 - - { 534, "MP", -1, 0, 0, "Pacific/Saipan" }, // Northern Mariana Islands (US) - { 535, "GU", -1, 0, 0, "Pacific/Guam" }, // Guam (US) - { 536, "NR", -1, 0, 0, "Pacific/Nauru" }, // Nauru - { 537, "PG", -1, 0, 0, "Pacific/Port_Moresby" }, // Papua New Guinea -- Port Moresby - { 539, "TO", -1, 0, 0, "Pacific/Tongatapu" }, // Tonga -- Nuku'alofa /*!*/ - { 540, "SB", -1, 0, 0, "Pacific/Guadalcanal" },// Solomon -- Honiara /*!*/ - { 541, "VU", -1, 0, 0, "Pacific/Efate" }, // Vanuatu -- Port Vila /*!*/ - { 542, "FJ", -1, 0, 0, "Pacific/Fiji" }, // Fiji -- Suva - { 543, "WF", -1, 0, 0, "Pacific/Wallis" }, // Wallis and Futuna (France) - { 544, "AS", -1, 0, 0, "Pacific/Pago_Pago" }, // American Samoa(US) -- Pago Pago - - { 545, "KI", 0, +12, +0, "Pacific/Tarawa" }, //Kiribati -- Tarawa Atoll - { 545, "KI", 1, +11, +0, "Pacific/Enderbury" }, // - { 545, "KI", 2, +14, +0, "Pacific/Kiritimati" }, // - - { 546, "NC", -1, 0, 0, "Pacific/Noumea" }, // New Caledonia(France) -- Noumea - - { 547, "PF", 0, -10, +0, "Pacific/Tahiti" }, // French Polynesia(France) -- Papeete - { 547, "PF", 1, -9, +0, "Pacific/Marquesas" },// - { 547, "PF", 2, -9, +0, "Pacific/Gambier" }, // - - { 548, "CK", -1, 0, 0, "Pacific/Rarotonga" }, // Cook Islands(NZ) -- Avarua /*!*/ - { 549, "WS", -1, 0, 0, "Pacific/Apia" }, // Samoa -- Apia - - { 550, "FM", 0, +11, +0, "Pacific/Pohnpei" }, // Micronesia -- Palikir - { 550, "FM", 1, +10, +0, "Pacific/Chuuk" }, // Truk - { 550, "FM", 2, +11, +0, "Pacific/Kosrae" }, // - - { 551, "MH", 0, +12, +0, "Pacific/Majuro" }, // Marshall Islands - { 551, "MH", 1, +12, +0, "Pacific/Kwajalein" },// - - { 552, "PW", -1, 0, 0, "Pacific/Palau" }, // Palau -- Ngerulmud - { 602, "EG", -1, 0, 0, "Africa/Cairo" }, // Cairo -- Cairo - { 603, "DZ", -1, 0, 0, "Africa/Algiers" }, // Algeri -- Algiers - { 604, "MA", -1, 0, 0, "Africa/Casablanca" }, // Morocco -- Rabat /*!*/ - { 605, "TN", -1, 0, 0, "Africa/Tunis" }, // Tunisia -- Tunis - { 606, "LY", -1, 0, 0, "Africa/Tripoli" }, // Libya -- Tripoli - { 607, "GM", -1, 0, 0, "Africa/Banjul" }, // Gambia -- Banjul - { 608, "SN", -1, 0, 0, "Africa/Dakar" }, // Senegal -- Dakar - { 609, "MR", -1, 0, 0, "Africa/Nouakchott" }, // Mauritania -- Nouakchott - { 610, "ML", -1, 0, 0, "Africa/Bamako" }, // Mali -- Bamako - { 611, "GN", -1, 0, 0, "Africa/Conakry" }, // Guinea -- Conakry - { 612, "CI", -1, 0, 0, "Africa/Abidjan" }, // lvory coast -- Yamoussoukro /*!*/ - { 613, "BF", -1, 0, 0, "Africa/Ouagadougou" }, // Burkina faso -- Ouagadougou - { 614, "NE", -1, 0, 0, "Africa/Niamey" }, // Niger -- Niamey - { 615, "TG", -1, 0, 0, "Africa/Lome" }, // Togo -- Lome - { 616, "BJ", -1, 0, 0, "Africa/Porto-Novo" }, // Benin -- Porto-Novo (n-project: Cotonou) - { 617, "MU", -1, 0, 0, "Indian/Mauritius" }, // Mauritius -- Port Louis (n-project: Plaisance-PlaineMagnien) - { 618, "LR", -1, 0, 0, "Africa/Monrovia" }, // Liberia -- Monrovia - { 619, "SL", -1, 0, 0, "Africa/Freetown" }, // Sierra leone -- Freetown - { 620, "GH", -1, 0, 0, "Africa/Accra" }, // Ghana -- Accra - { 621, "NG", -1, 0, 0, "Africa/Lagos" }, // Nigeria -- Abuja /*!*/ - { 622, "TD", -1, 0, 0, "Africa/Ndjamena" }, // Chad -- N'Djamena - { 623, "CF", -1, 0, 0, "Africa/Bangui" }, // Central african republic -- Bangui - { 624, "CM", -1, 0, 0, "Africa/Douala" }, // Cameroon -- Yaounde /*!*/ - { 625, "CV", -1, 0, 0, "Atlantic/Cape_Verde" },// Cape verde -- Praia (n-project: IlhaDoSal) - { 626, "ST", -1, 0, 0, "Africa/Sao_Tome" }, // Sao tome and principe -- Sao Tome - { 627, "GQ", -1, 0, 0, "Africa/Malabo" }, // Equatorial guinea -- Malabo - { 628, "GA", -1, 0, 0, "Africa/Libreville" }, // Gabon -- Libreville - { 629, "CG", -1, 0, 0, "Africa/Brazzaville" }, // Republic of the congo -- Brazzaville - - { 630, "CD", 0, +1, +0, "Africa/Kinshasa" }, // Democratic republic of the congo -- Kinshasa - { 630, "CD", 1, +2, +0, "Africa/Lubumbashi" },// - - { 631, "AO", -1, 0, 0, "Africa/Luanda" }, // Angola -- Luanda - { 632, "GW", -1, 0, 0, "Africa/Bissau" }, // Guinea-bissau -- Bissau - { 633, "SC", -1, 0, 0, "Indian/Mahe" }, // Seychelles -- Victoria /*!*/ - { 634, "SD", -1, 0, 0, "Africa/Khartoum" }, // Sudan -- Khartoum - { 635, "RW", -1, 0, 0, "Africa/Kigali" }, // Rwanda -- Kigali - { 636, "ET", -1, 0, 0, "Africa/Addis_Ababa" }, // Ethiopia -- Addis Ababa - { 637, "SO", -1, 0, 0, "Africa/Mogadishu" }, // Somalia -- Mogadishu - { 638, "DJ", -1, 0, 0, "Africa/Djibouti" }, // Djibouti -- Djibouti - { 639, "KE", -1, 0, 0, "Africa/Nairobi" }, // Kenya -- Nairobi - { 640, "TZ", -1, 0, 0, "Africa/Dar_es_Salaam" }, // Tanzania -- Dar es Salaam - { 641, "UG", -1, 0, 0, "Africa/Kampala" }, // Uganda -- Kampala (n-project: Entebbe) - { 642, "BI", -1, 0, 0, "Africa/Bujumbura" }, // Burundi -- Bujumbura - { 643, "MZ", -1, 0, 0, "Africa/Maputo" }, // Mozambique -- Maputo - { 645, "ZM", -1, 0, 0, "Africa/Lusaka" }, // Zambia -- Lusaka - { 646, "MG", -1, 0, 0, "Indian/Antananarivo" },// Madagascar -- Antananarivo - { 647, "RE", -1, 0, 0, "Indian/Reunion" }, // Reunion (France) -- no capital - { 648, "ZW", -1, 0, 0, "Africa/Harare" }, // Zimbabwe -- Harare - { 649, "NA", -1, 0, 0, "Africa/Windhoek" }, // Namibia -- Windhoek - { 650, "MW", -1, 0, 0, "Africa/Blantyre" }, // Malawi -- Lilongwe /*!*/ - { 651, "LS", -1, 0, 0, "Africa/Maseru" }, // Lesotho -- Maseru - { 652, "BW", -1, 0, 0, "Africa/Gaborone" }, // Botswana -- Gaborone - { 653, "SZ", -1, 0, 0, "Africa/Mbabane" }, // Swaziland -- Mbabane - { 654, "KM", -1, 0, 0, "Indian/Comoro" }, // Comoros -- Moroni - { 655, "ZA", -1, 0, 0, "Africa/Johannesburg" },// South africa -- Pretoria (administrative); Cape Town (legislative); Bloemfontein (judiciary) - { 657, "ER", -1, 0, 0, "Africa/Asmara" }, // Eritrea - { 702, "BZ", -1, 0, 0, "America/Belize" }, // Belize -- Belmopan - { 704, "GT", -1, 0, 0, "America/Guatemala" }, // Guatemala -- Guatemala City - { 706, "SV", -1, 0, 0, "America/El_Salvador" },// El salvador -- San Salvador - { 708, "HN", -1, 0, 0, "America/Tegucigalpa" },// Honduras -- Tegucigalpa - { 710, "NI", -1, 0, 0, "America/Managua" }, // Nicaragua -- Managua - { 712, "CR", -1, 0, 0, "America/Costa_Rica" }, // Costa rica -- San Jose - { 714, "PA", -1, 0, 0, "America/Panama" }, // Panama -- Panama City - { 716, "PE", -1, 0, 0, "America/Lima" }, // Peru -- Lima - - { 722, "AR", 0, -3, +0, "America/Argentina/Buenos_Aires" }, // Argentina -- Buenos Aires - { 722, "AR", 1, -3, +0, "America/Argentina/Cordoba" }, // - { 722, "AR", 2, -3, +0, "America/Argentina/Salta" }, // - { 722, "AR", 3, -3, +0, "America/Argentina/Jujuy" }, // - { 722, "AR", 4, -3, +0, "America/Argentina/Tucuman" }, // - { 722, "AR", 5, -3, +0, "America/Argentina/Catamarca" }, // - { 722, "AR", 6, -3, +0, "America/Argentina/La_Rioja" }, // - { 722, "AR", 7, -3, +0, "America/Argentina/San_Juan" }, // - { 722, "AR", 8, -3, +0, "America/Argentina/Mendoza" }, // - { 722, "AR", 9, -3, +0, "America/Argentina/San_Luis" }, // - { 722, "AR", 10, -3, +0, "America/Argentina/Rio_Gallegos" }, // - { 722, "AR", 11, -3, +0, "America/Argentina/Ushuaia" }, // - - { 724, "BR", 0, -3, +1, "America/Sao_Paulo" }, // Brazil -- Brasilia /*!*/ - { 724, "BR", 1, -2, +0, "America/Noronha" }, // - { 724, "BR", 2, -3, +0, "America/Belem" }, // - { 724, "BR", 3, -3, +0, "America/Fortaleza" }, // - { 724, "BR", 4, -3, +0, "America/Recife" }, // - { 724, "BR", 5, -3, +0, "America/Araguaina" }, // - { 724, "BR", 6, -3, +0, "America/Maceio" }, // - { 724, "BR", 7, -3, +0, "America/Bahia" }, // - { 724, "BR", 8, -4, +1, "America/Campo_Grande" }, // - { 724, "BR", 9, -4, +1, "America/Cuiaba" }, // - { 724, "BR", 10, -4, +0, "America/Santarem" }, // - { 724, "BR", 11, -4, +0, "America/Porto_Velho" }, // - { 724, "BR", 12, -4, +0, "America/Boa_Vista" }, // - { 724, "BR", 13, -4, +0, "America/Manaus" }, // - { 724, "BR", 14, -4, +0, "America/Eirunepe" }, // - { 724, "BR", 15, -4, +0, "America/Rio_Branco" }, // - - { 730, "CL", 0, -4, +1, "America/Santiago" }, // Chile -- Santiago - { 730, "CL", 1, -6, +1, "Pacific/Easter" }, // - - { 734, "VE", -1, 0, 0, "America/Caracas" }, // Venezuela -- Caracas - { 736, "BO", -1, 0, 0, "America/La_Paz" }, // Bolivia -- La Paz (administrative); Sucre (judicial) - { 738, "GY", -1, 0, 0, "America/Guyana" }, // Guyana -- Georgetown - - { 740, "EC", 0, -5, +0, "America/Guayaquil" },// Ecuador -- Quito /*!*/ - { 740, "EC", 1, -6, +0, "Pacific/Galapagos" },// - - { 742, "GF", -1, 0, 0, "America/Cayenne" }, // French Guiana (France) - { 744, "PY", -1, 0, 0, "America/Asuncion" }, // Paraguay -- Asuncion - { 746, "SR", -1, 0, 0, "America/Paramaribo" }, // Suriname -- Paramaribo - { 748, "UY", -1, 0, 0, "America/Montevideo" }, // Uruguay -- Montevideo - { 750, "FK", -1, 0, 0, "Atlantic/Stanley" }, // Falkland Islands (Malvinas) - - { -1, NULL, -1, -1, -1, NULL }, -}; - -/* - * FIXME: need to check exceptional timezone - */ -static NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo_by_mcc_timezone(int mcc, int tz, int dst, int dst_valid) -{ - NITZ_MCC_TZFILE_MAP *t = NULL; - int calc_tz = 0; - - dbg("Request mcc: [%d], tz: [%d], dst: [%d], dst_valid: [%d]", - mcc, tz, dst, dst_valid); - filelog("Find tzfinfo - multi timezone (mcc = %d)", mcc); - filelog("+- wanted tz: %d, dst: %d, dst_valid: %d", tz, dst, dst_valid); - - t = nitz_table_mcc_tzfile; - while (1) { - if (t->mcc == -1) - return NULL; - - if (t->mcc == mcc) { - calc_tz = t->std_timezone * 60; - dbg("mcc(%d) matched!! [tz=%d, dst=%d, calc_tz=%d, city=%s]", mcc, t->std_timezone, t->dst, calc_tz, t->city); - - filelog("+- tz: %d (%d), dst: %d, calc_tz: %d, city: %s", - t->std_timezone, t->std_timezone*60, t->dst, calc_tz, t->city); - - if (dst && dst_valid) { - if (!t->dst) - goto CONT; - - calc_tz += t->dst * 60; - } - - if (calc_tz == tz) - return t; - } -CONT: - t++; - } - - return NULL; -} - -static NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo_by_mcc(int mcc) -{ - NITZ_MCC_TZFILE_MAP *t = NULL; - - if (mcc <= 0) - return NULL; - - t = nitz_table_mcc_tzfile; - while (1) { - if (t->mcc == -1) - return NULL; - - if (t->mcc == mcc) - return t; - - t++; - } - - return NULL; -} - -static gboolean nitz_is_multi_timezone(NITZ_MCC_TZFILE_MAP *m) -{ - if (m->id == -1) - return FALSE; - - return TRUE; -} - -NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo(int mcc, int gmtoff, int dstoff, int isdst) -{ - NITZ_MCC_TZFILE_MAP *m; - - m = nitz_find_tzinfo_by_mcc(mcc); - if (nitz_is_multi_timezone(m)) { - dbg("Multi timezone"); - m = nitz_find_tzinfo_by_mcc_timezone(mcc, gmtoff, dstoff, isdst); - } - - return m; -} - -int nitz_self_check_tzfile(void) -{ - NITZ_MCC_TZFILE_MAP *t = NULL; - struct stat file_info; - char buf[255] = {0,}; - int ret = TRUE; - - t = nitz_table_mcc_tzfile; - while (1) { - if (t->mcc == -1) - return ret; - - /* check tzfile */ - snprintf (buf, 255, "/usr/share/zoneinfo/%s", t->city); - if (stat(buf, &file_info) == -1) { - filelog("file not exist!! [mcc=%d, tz=%3d, %s]", t->mcc, t->std_timezone, buf); - ret = FALSE; - } - - t++; - } - - return ret; -} diff --git a/src/citylist.h b/src/citylist.h deleted file mode 100644 index 8e8bfaf..0000000 --- a/src/citylist.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * tel-plugin-nitz - * - * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __NITZ_CITYLIST_H__ -#define __NITZ_CITYLIST_H__ - -/* - * http://en.wikipedia.org/wiki/List_of_mobile_country_codes - * http://worldtimeengine.com - */ - -typedef struct { - int mcc; - char *country; /* iso3166 */ - int id; /* id for city name (multi timezone in one country) */ - int std_timezone; - int dst; - char *city; /* timezone city filename */ -} NITZ_MCC_TZFILE_MAP; - -NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo(int mcc, int gmtoff, int dstoff, int isdst); -int nitz_self_check_tzfile(void); - -#endif diff --git a/src/desc-nitz.c b/src/desc-nitz.c index 341321b..0f21cdc 100644 --- a/src/desc-nitz.c +++ b/src/desc-nitz.c @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -31,39 +32,457 @@ #include "common.h" #include "time_update.h" +#include +#include +#include + +#define MCCTABLE_DIR_PATH "/opt/data/etc/mcctable.xml" + #ifndef PLUGIN_VERSION #define PLUGIN_VERSION 1 #endif -static enum tcore_hook_return on_hook_network_timeinfo(Server *s, - CoreObject *source, - enum tcore_notification_command command, - unsigned int data_len, void *data, void *user_data) +#define VCONFKEY_WECONN_ALL_CONNECTED "memory/private/weconn/all_connected" +#define VCONFKEY_SAP_CONNECTION_TYPE "memory/private/sap/conn_type" + +typedef enum SapConnType { + SAP_ALL = 0x00, /* All connectivity */ + SAP_BT = 0x01, /* BT connectivity */ + SAP_BLE = 0x02, /* BLE connectivity */ + SAP_TCP_IP = 0x04, /* TCP connectivity */ + SAP_USB = 0x08, /* USB connectivity */ + SAP_MOBILE = 0x10, /* SCS connectivity */ + SAP_CONNECTIVITY_END = 0xFF /* End of Connectivity */ +} SapConnType; + +struct nitz_time_update_s { + CoreObject *co_network; + + struct tnoti_network_timeinfo *timeinfo; + struct nitz_custom_data *custom_data; + time_t start_time; +}; + +static void __load_XML(char *docname, char *groupname, void **i_doc, void **i_root_node) +{ + xmlDocPtr *doc = (xmlDocPtr *)i_doc; + xmlNodePtr *root_node = (xmlNodePtr *)i_root_node; + + dbg("docname:%s, groupname:%s", docname, groupname); + + *doc = xmlParseFile(docname); + if (*doc) { + *root_node = xmlDocGetRootElement(*doc); + if (*root_node) { + dbg("*root_node->name:%s", (*root_node)->name); + if (0 == xmlStrcmp((*root_node)->name, (const xmlChar *)groupname)) { + *root_node = (*root_node)->xmlChildrenNode; + } else { + xmlFreeDoc(*doc); + *doc = NULL; + *root_node = NULL; + } + } else { + xmlFreeDoc(*doc); + *doc = NULL; + } + } else + err("Cannot parse doc(%s)", docname); +} + +static void __unload_XML(void **i_doc, void **i_root_node) +{ + xmlDocPtr *doc = (xmlDocPtr *)i_doc; + xmlNodePtr *root_node = (xmlNodePtr *)i_root_node; + + dbg("unloading XML"); + if (doc && *doc) { + xmlFreeDoc(*doc); + *doc = NULL; + if (root_node) + *root_node = NULL; + } +} + +char *__nitz_get_country_code_for_mcc(char *operator_mcc, struct nitz_custom_data *data) +{ + xmlNodePtr cur = NULL; + xmlNode *cur_node = NULL; + char *mcc_str = NULL, *iso = NULL; + void *xml_doc = NULL, *xml_root_node = NULL; + + dbg("operator_mcc = %s", operator_mcc); + + iso = (char *)g_hash_table_lookup(data->mcctable_hash, operator_mcc); + if (iso) { + dbg("Found a record in cache (mcc[%s], iso[%s])", operator_mcc, iso ? iso : ""); + return g_strdup(iso); + } + + __load_XML(MCCTABLE_DIR_PATH, "mcctable", &xml_doc, &xml_root_node); + if (!xml_root_node) { + err("mcctable.xml load error"); + return NULL; + } + + /* Get iso country code from mcctable for mcc */ + cur = xml_root_node; + for (cur_node = cur; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + mcc_str = (char *)xmlGetProp(cur_node, (const xmlChar *)"mcc"); + if (g_strcmp0(operator_mcc, mcc_str) == 0) { + iso = g_strdup((char *)xmlGetProp(cur_node, (const xmlChar *)"iso")); + dbg("Found a record(mcc[%s], iso[%s])", mcc_str, iso ? iso : ""); + break; + } + } + } + __unload_XML(&xml_doc, &xml_root_node); + if (iso) + g_hash_table_insert(data->mcctable_hash, g_strdup(operator_mcc), g_strdup(iso)); + return iso; +} + +static enum ConnMode __nitz_get_device_connection_mode(void) +{ + int all_connected = FALSE; + int sap_conn_type = 0; + +#ifdef TIZEN_FEATURE_COMPANION_MODE_ENABLE + vconf_get_int(VCONFKEY_WECONN_ALL_CONNECTED, &all_connected); + vconf_get_int(VCONFKEY_SAP_CONNECTION_TYPE, &sap_conn_type); +#endif + info("(%s : %d) (%s : %d)", VCONFKEY_WECONN_ALL_CONNECTED, all_connected, VCONFKEY_SAP_CONNECTION_TYPE, sap_conn_type); + + if (!all_connected) { + return CONN_MODE_STANDALONE; + } else { + switch (sap_conn_type) { + case SAP_BT: + return CONN_MODE_COMPAINION; + + case SAP_MOBILE: + return CONN_MODE_REMOTE; + + default: + err("unknown type"); + break; + } + } + return CONN_MODE_UNKNOWN; +} + +static gboolean _check_area_changed(char *iso) +{ + char *saved_iso = NULL; + gboolean area_changed = TRUE; + + saved_iso = vconf_get_str(VCONFKEY_TELEPHONY_PRIVATE_NITZ_ISO); + if (saved_iso) { + info("saved iso:[%s], mcc iso:[%s]", saved_iso, iso); + if (g_ascii_strcasecmp(saved_iso, iso) == 0) + area_changed = FALSE; + + free(saved_iso); + } + + return area_changed; +} + +static void _check_fix_time_zone(struct nitz_custom_data *custom_data) +{ + char mcc_str[4] = {0,}; + char *iso = NULL; + int mcc = 0; + int icc_card_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN; + enum telephony_network_service_type svc_type = NETWORK_SERVICE_TYPE_UNKNOWN; + Server *s = tcore_plugin_ref_server(custom_data->plugin); + GList *tz_list = NULL; + char *timezone_name = NULL; + int tz_count = 0; + + if (!custom_data->need_fix_zone) { + info("We don't need to fix timezone"); + return; + } + + if (!nitz_is_auto_timezone()) { + info("We don't need to fix timezone in Manual timezone mode"); + return; + } + + vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &icc_card_exist); + if (icc_card_exist != VCONFKEY_TELEPHONY_SIM_INSERTED) { + if (tcore_server_get_modems_count(s) == 2) { + int icc_card2_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN; + vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT2, &icc_card2_exist); + if (icc_card2_exist != VCONFKEY_TELEPHONY_SIM_INSERTED) { + info("We don't need to fix timezone. Icc card is not exist."); + custom_data->wait_for_icc_card = TRUE; + return; + } + } else { + info("We don't need to fix timezone. Icc card is not exist."); + custom_data->wait_for_icc_card = TRUE; + return; + } + } + + tcore_network_get_service_type(custom_data->co_network, &svc_type); + if (svc_type <= NETWORK_SERVICE_TYPE_SEARCH) { + info("We don't need to fix timezone. Not registered network yet"); + custom_data->wait_for_net_registration = TRUE; + return; + } else { + custom_data->wait_for_net_registration = FALSE; + } + + memcpy(mcc_str, custom_data->plmn, 3); + mcc = atoi(mcc_str); + iso = __nitz_get_country_code_for_mcc(mcc_str, custom_data); + if (iso) { + tz_list = nitz_get_tzlist(iso, NULL); + tz_count = g_list_length(tz_list); + dbg("tz_count - %d", tz_count); + if (tz_count > 0) { + if (_check_area_changed(iso)) { + timezone_name = tz_list->data; + if (tz_count > 1) { + info("Multi timezone, Can not select (Need gmtoff, dmtoff, ..."); + } else { + info("Single timezone. Apply (mcc:[%d] iso:[%s] zone:[%s])", mcc, iso, timezone_name); + nitz_apply_tzfile(timezone_name); + } + } else { + info("Same Area. Do not change timezone now"); + } + goto EXIT; + } else { + info("timezone not found for mcc[%d] and iso[%s]", mcc, iso); + } + } else { + dbg("country code is NULL for mcc %d", mcc); + } + +EXIT: + g_list_free_full(tz_list, g_free); + g_free(iso); +} + +static gboolean _update_network_timeinfo(gpointer user_data) +{ + struct nitz_time_update_s *time_update = user_data; + struct tnoti_network_timeinfo *timeinfo = NULL; + struct nitz_custom_data *custom_data = NULL; + time_t current_time = 0; + gint delay = 0; + + if (!time_update) + return FALSE; + + if (nitz_is_auto_timezone()) { + /* Time update delay is calculated only for Automatic time update mode. + * For manual time update mode, we can't rely on system time for current time to derive offset/delay + */ + time(¤t_time); + delay = current_time - time_update->start_time; + info("Enqueued_timestamp[%u] Dequeued_timestamp[%u] delay[%d]", time_update->start_time, current_time, delay); + } + + timeinfo = time_update->timeinfo; + custom_data = time_update->custom_data; + custom_data->nitz_updated = TRUE; + custom_data->need_fix_zone = FALSE; + + info("[TIMESTAMP][STEP3-Processing] %04d-%02d-%02d %02d:%02d:%02d wday=%d GMT:%d, dstoff:%d, is_dst:%d", + timeinfo->year, timeinfo->month, timeinfo->day, + timeinfo->hour, timeinfo->minute, timeinfo->second, + timeinfo->wday, timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst); + + if (CONN_MODE_COMPAINION == __nitz_get_device_connection_mode()) { + g_free(timeinfo); + g_free(time_update); + info("[TIMESTAMP] device is in companion mode! ignore NITZ update"); + return FALSE; + } + + if (!custom_data->co_network) + custom_data->co_network = time_update->co_network; + + if (strlen(timeinfo->plmn) == 0 && custom_data->plmn != NULL) { + /* Updated PLMN from custom_data incase when received PLMN is empty. */ + info("Received PLMN is empty, so use cached PLMN"); + g_strlcpy(timeinfo->plmn, custom_data->plmn, strlen(custom_data->plmn)+1); + } + + nitz_time_update(timeinfo, custom_data, delay); + + g_free(timeinfo); + g_free(time_update); + + return FALSE; +} + +static gboolean _process_nitz_pending(gpointer user_data) { + struct nitz_custom_data *custom_data = user_data; + struct nitz_time_update_s *time_update = NULL; + struct tnoti_network_timeinfo *timeinfo = NULL; + + if (!custom_data) + return FALSE; + + while (1) { + time_update = g_queue_pop_head(custom_data->nitz_pending_queue); + if (!time_update) + break; + + timeinfo = time_update->timeinfo; + if (!timeinfo) + continue; + + if (g_queue_is_empty(custom_data->nitz_pending_queue)) + break; + + info("[TIMESTAMP][STEP2-Discard] %04d-%02d-%02d %02d:%02d:%02d wday=%d GMT:%d, dstoff:%d, is_dst:%d", + timeinfo->year, timeinfo->month, timeinfo->day, + timeinfo->hour, timeinfo->minute, timeinfo->second, + timeinfo->wday, timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst); + + g_free(timeinfo); + g_free(time_update); + } + + _update_network_timeinfo(time_update); + return FALSE; +} + +static enum tcore_hook_return on_hook_network_regist(Server *s, + CoreObject *source, enum tcore_notification_command command, + unsigned int data_len, void *data, void *user_data) +{ + struct nitz_custom_data *custom_data = user_data; + struct tnoti_network_registration_status *info = data; + + if (!custom_data->co_network) + custom_data->co_network = source; + + /* + * Handle MCC changed scenario - + * If MCC is changed and network is registered, update timezone + */ + if ((info->service_type >= NETWORK_SERVICE_TYPE_SEARCH) + && (custom_data->wait_for_net_registration)) + _check_fix_time_zone(custom_data); + + return TCORE_HOOK_RETURN_CONTINUE; +} + +static enum tcore_hook_return on_hook_network(Server *s, CoreObject *source, + enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + struct nitz_custom_data *custom_data = user_data; + struct tnoti_network_change *info = data; + gboolean is_mcc_changed = FALSE; + + if (!info || strlen(info->plmn) == 0) { + info("Invalid data"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + if (!custom_data->co_network) + custom_data->co_network = source; + + /* + * Handle MCC changed scenario - + * If MCC is changed and network is registered, update timezone + */ + if ((custom_data->plmn && strncmp(info->plmn, custom_data->plmn, 3)) || (!custom_data->plmn)) { + info("MCC change (%s) -> (%s)", custom_data->plmn ? custom_data->plmn : "", info->plmn); + g_free(custom_data->plmn); + custom_data->plmn = g_strdup(info->plmn); + is_mcc_changed = TRUE; + } + + if (is_mcc_changed) { + if (CONN_MODE_COMPAINION == __nitz_get_device_connection_mode()) { + info("device is in companion mode! ignore MCC change"); + } else { + custom_data->need_fix_zone = TRUE; + _check_fix_time_zone(custom_data); + } + } + + return TCORE_HOOK_RETURN_CONTINUE; +} + +static enum tcore_hook_return on_hook_network_timeinfo(Server *s, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + struct nitz_time_update_s *time_update; struct tnoti_network_timeinfo *timeinfo = data; - gboolean flag_auto_update = FALSE; + struct nitz_custom_data *custom_data = user_data; filelog("NITZ !! (time(NULL) = %u)", (unsigned int)time(NULL)); - dbg("+- %04d-%02d-%02d %02d:%02d:%02d wday=%d", + + info("[TIMESTAMP][STEP1-AddQueue] %04d-%02d-%02d %02d:%02d:%02d wday=%d GMT:%d, dstoff:%d, is_dst:%d", timeinfo->year, timeinfo->month, timeinfo->day, timeinfo->hour, timeinfo->minute, timeinfo->second, - timeinfo->wday); - dbg("+- GMT-offset:%d, DST-offset:%d, is_dst:%d", - timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst); + timeinfo->wday, timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst); + + /* Allocate memory */ + time_update = g_try_malloc0(sizeof(struct nitz_time_update_s)); + if (time_update == NULL) { + err("Memory allocation failed"); + return TCORE_HOOK_RETURN_CONTINUE; + } - vconf_get_bool(VCONFKEY_SETAPPL_STATE_AUTOMATIC_TIME_UPDATE_BOOL, - &flag_auto_update); - if (flag_auto_update == FALSE) - dbg("manual time update mode"); + time_update->custom_data = custom_data; + time_update->timeinfo = g_memdup(timeinfo, sizeof(struct tnoti_network_timeinfo)); + time_update->co_network = source; - nitz_time_update(timeinfo, flag_auto_update); + if (g_queue_is_empty(custom_data->nitz_pending_queue)) { + info("No pending NITZ"); + g_idle_add(_process_nitz_pending, custom_data); + } + info("Add nitz info to queue"); + time(&time_update->start_time); + g_queue_push_tail(custom_data->nitz_pending_queue, time_update); return TCORE_HOOK_RETURN_CONTINUE; } +static void on_vconf_sim_slot_state(keynode_t *node, void *user_data) +{ + int icc_card_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN; + struct nitz_custom_data *data = user_data; + Server *s = tcore_plugin_ref_server(data->plugin); + + vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &icc_card_exist); + if (icc_card_exist == VCONFKEY_TELEPHONY_SIM_INSERTED) + goto UPDATE; + else { + if (tcore_server_get_modems_count(s) == 2) { + int icc_card2_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN; + vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT2, &icc_card2_exist); + if (icc_card2_exist == VCONFKEY_TELEPHONY_SIM_INSERTED) + goto UPDATE; + } + return; + } +UPDATE: + { + struct nitz_custom_data *data = user_data; + if (data->wait_for_icc_card) { + info("ICC CARD INSERTED. check timezone again"); + _check_fix_time_zone(user_data); + data->wait_for_icc_card = FALSE; + } + } +} + static gboolean on_load() { - dbg("Load!!!"); + dbg("i'm load!"); return TRUE; } @@ -71,26 +490,78 @@ static gboolean on_load() static gboolean on_init(TcorePlugin *p) { Server *s; + struct nitz_custom_data *data; + guint modems_count; - dbg("Init!!!"); + if (!p) + return FALSE; + + dbg("i'm init!"); s = tcore_plugin_ref_server(p); - if (s == NULL) + if (!s) + return FALSE; + + data = calloc(sizeof(struct nitz_custom_data), 1); + if (!data) return FALSE; - tcore_server_add_notification_hook(s, TNOTI_NETWORK_TIMEINFO, - on_hook_network_timeinfo, NULL); + data->plugin = p; + tcore_plugin_link_user_data(p, data); + + data->nitz_updated = FALSE; + data->need_fix_zone = FALSE; + data->mcctable_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + data->nitz_pending_queue = g_queue_new(); + g_queue_init(data->nitz_pending_queue); + + tcore_server_add_notification_hook(s, TNOTI_NETWORK_CHANGE, on_hook_network, data); + tcore_server_add_notification_hook(s, TNOTI_NETWORK_REGISTRATION_STATUS, on_hook_network_regist, data); + tcore_server_add_notification_hook(s, TNOTI_NETWORK_TIMEINFO, on_hook_network_timeinfo, data); + + vconf_notify_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT, on_vconf_sim_slot_state, data); + + modems_count = tcore_server_get_modems_count(s); + dbg("get modems count - %d", modems_count); + if (modems_count == 2) + vconf_notify_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT2, on_vconf_sim_slot_state, data); return TRUE; } static void on_unload(TcorePlugin *p) { - dbg("Unload"); + struct nitz_custom_data *data; + Server *s; + guint modems_count; + + dbg("i'm unload"); + + data = tcore_plugin_ref_user_data(p); + if (!data) + return; + + if (data->plmn) + g_free(data->plmn); + + if (data->mcctable_hash) + g_hash_table_destroy(data->mcctable_hash); + + s = tcore_plugin_ref_server(p); + tcore_server_remove_notification_hook(s, on_hook_network); + tcore_server_remove_notification_hook(s, on_hook_network_regist); + tcore_server_remove_notification_hook(s, on_hook_network_timeinfo); + + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT, on_vconf_sim_slot_state); + modems_count = tcore_server_get_modems_count(s); + dbg("get modems count - %d", modems_count); + if (modems_count == 2) + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT2, on_vconf_sim_slot_state); + + free(data); } -EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = -{ +EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = { .name = "NITZ", .priority = TCORE_PLUGIN_PRIORITY_MID, .version = PLUGIN_VERSION, diff --git a/src/time_update.c b/src/time_update.c index 29d1438..faf8ce4 100644 --- a/src/time_update.c +++ b/src/time_update.c @@ -31,57 +31,194 @@ #include #include #include -#include +#include +#include + #include "common.h" #include "time_update.h" -#include "citylist.h" #define BUF_SIZE 255 #define PATH_LOCALTIME "/opt/etc/localtime" #define PATH_ZONEINFO "/usr/share/zoneinfo" +#define VCONFKEY_TELEPHONY_NITZ_ISO "db/private/telephony/nitz_iso" + +gboolean nitz_is_auto_timezone(void) +{ + gboolean auto_timezone; + vconf_get_bool(VCONFKEY_SETAPPL_STATE_AUTOMATIC_TIME_UPDATE_BOOL, &auto_timezone); + if (auto_timezone == FALSE) { + dbg("Manual time update mode."); + return FALSE; + } else { + dbg("Automatic time update mode."); + return TRUE; + } +} + +static int nitz_get_uptime(void) +{ + struct sysinfo sys_info; + + if (sysinfo(&sys_info) == 0) { + info("uptime: %ld secs", sys_info.uptime); + return sys_info.uptime; + } + + return 0; +} + +gboolean nitz_set_time(time_t new_time) +{ + int ret = 0; + + vconf_set_int(VCONFKEY_TELEPHONY_NITZ_GMT, new_time); + vconf_set_int(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, nitz_get_uptime()); + + if (!nitz_is_auto_timezone()) { + info("[TIMESTAMP] Automatic time update was disabled. We don't need to set time"); + return FALSE; + } + + /* + * - Apply system time(GMT) + */ + info("[TIMESTAMP][Before] NITZ GMT Time = %ld", new_time); + + /* Acquire lock */ + ret = device_power_request_lock(POWER_LOCK_CPU, 0); + if (ret < 0) + err("ret : (0x%x)", ret); -int nitz_apply_tzfile(const char *tzfilename, gboolean mode_auto) + ret = alarmmgr_set_systime(new_time); + if (ret < 0) + info("[TIMESTAMP] alarmmgr_set_systime fail. (ret=%d)", ret); + else + info("[TIMESTAMP][After] alarm_set_time(%ld) success", new_time); + + /* Release lock */ + ret = device_power_release_lock(POWER_LOCK_CPU); + if (ret < 0) + err("ret : (0x%x)", ret); + return TRUE; +} + +gboolean nitz_apply_tzfile(const char *tzfilename) { char buf[BUF_SIZE] = {0, }; - int ret; + char current_tz[BUF_SIZE] = {0, }; + int ret = -1; + ssize_t len; - vconf_set_str(VCONFKEY_TELEPHONY_NITZ_ZONE, tzfilename); + if (!tzfilename) { + err("tzfilename is NULL"); + return FALSE; + } - if (mode_auto == FALSE) - return 0; + if (!nitz_is_auto_timezone()) { + info("[TIMESTAMP] Automatic time update was disabled. We don't need to set time"); + return FALSE; + } snprintf(buf, BUF_SIZE, "%s/%s", PATH_ZONEINFO, tzfilename); - ret = deviced_set_timezone(buf); - filelog("set (%s) timezone file. ret=%d", buf, ret); + len = readlink(PATH_LOCALTIME, current_tz, BUF_SIZE-1); + if (len < 0) { + err("Fail to get Current Zone Info"); + } else { + if (g_strcmp0(current_tz, buf) == 0) { + info("[TIMESTAMP] We don't need to set timezone again (Already applied)"); + return FALSE; + } else { + info("Current TZ:[%s] New TZ:[%s]", current_tz, buf); + } + } + + filelog("[TIMESTAMP][Before] timezone will be set"); + + /* Acquire lock */ + ret = device_power_request_lock(POWER_LOCK_CPU, 0); + if (ret < 0) + err("ret : (0x%x)", ret); + + ret = alarmmgr_set_timezone(buf); + + /* Release lock */ + device_power_release_lock(POWER_LOCK_CPU); + if (ret < 0) + err("ret : (0x%x)", ret); + + filelog("set (%s) alarmmgr_set_timezone ret=%d", buf, ret); sync(); tzset(); - filelog("+- Result: tzname=[%s, %s], timezone=%ld, daylight=%d", - tzname[0], tzname[1], timezone, daylight); + filelog("[TIMESTAMP][After] tzname=[%s, %s], timezone=%ld, daylight=%d", + tzname[0], tzname[1], timezone, daylight); - return ret; + if (ret != 0) + return FALSE; + else + return TRUE; } -long nitz_get_uptime() +static gboolean __update_timezone_by_offset(const struct tnoti_network_timeinfo *ti, char *iso) { - struct sysinfo info; + char *timezone_name = NULL; + GList *tz_list = NULL; + int tz_count = 0; + gboolean ret = FALSE; + gboolean found = FALSE; - if (sysinfo(&info) == 0) { - dbg("uptime: %ld secs", info.uptime); - return info.uptime; + tz_list = nitz_get_tzlist(iso, ti); + tz_count = g_list_length(tz_list); + if (tz_count == 1) { + timezone_name = tz_list ? tz_list->data : NULL; + found = timezone_name ? TRUE : FALSE; + info("Single timezone(%s)", timezone_name); + } else { + UChar utf16_timezone[NITZ_TIMEZONE_MAX_LEN] = { 0 }; + UCalendar *cal = NULL; + gboolean in_dst = FALSE; + UErrorCode ec = U_ZERO_ERROR; + GList *list = NULL; + + info("Multi timezone. # of TZ : [%d]", tz_count); + for (list = tz_list; list != NULL; list = g_list_next(list)) { + timezone_name = list->data; + if (strlen(timezone_name) > 0) { + u_uastrncpy(utf16_timezone, timezone_name, NITZ_TIMEZONE_MAX_LEN); + cal = ucal_open(utf16_timezone, u_strlen(utf16_timezone), uloc_getDefault(), UCAL_TRADITIONAL, &ec); + if (cal == NULL) { + err("ucal_open returns NULL"); + break; + } + in_dst = ucal_inDaylightTime(cal, &ec); + dbg("TZ DST:[%d] WANTED DST:[%d][%d]", in_dst, ti->isdst, ti->dstoff); + if (ti->dstoff == (int)in_dst) { + found = TRUE; + info("(%s) was selected", timezone_name); + ucal_close(cal); + break; + } + ucal_close(cal); + } + } } - return 0; + if (found) + ret = nitz_apply_tzfile(timezone_name); + else + info("[TIMESTAMP] Fail to find timezone"); + + g_list_free_full(tz_list, g_free); + return ret; } -static gboolean update_time(const struct tnoti_network_timeinfo *ti, - gboolean mode_auto) +static gboolean __update_time(const struct tnoti_network_timeinfo *ti, + struct nitz_custom_data *data, gint delay) { struct tm tm_time; time_t tt_gmt_nitz; - int ret; memset(&tm_time, 0, sizeof(struct tm)); tm_time.tm_year = ti->year - 1900 + 2000; @@ -93,74 +230,101 @@ static gboolean update_time(const struct tnoti_network_timeinfo *ti, tm_time.tm_wday = ti->wday; tm_time.tm_isdst = ti->dstoff; - tt_gmt_nitz = timegm(&tm_time); - tt_gmt_nitz -= ti->gmtoff * 60; - dbg("NITZ GMT Time = %ld", tt_gmt_nitz); - - vconf_set_int(VCONFKEY_TELEPHONY_NITZ_GMT, tt_gmt_nitz); - vconf_set_int(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, nitz_get_uptime()); - - if (mode_auto == FALSE) { - return FALSE; - } - + tt_gmt_nitz = timegm(&tm_time)+delay; +#ifdef TIZEN_FEATURE_NEED_RESTORED_GMT /* - * - Apply system time (GMT) + * Need to set GMT+0 time. + * but, in case of IMC-modem, CP send the time applied GMT.(e.g., GMT+9 in Korea) + * so, restore GMT+0 time. */ - ret = deviced_set_datetime(tt_gmt_nitz); - if (ret < 0) { - filelog("deviced_set_datetime(%ld) failed. ret = %d", - tt_gmt_nitz, ret); - return FALSE; - } else { - filelog("deviced_set_datetime(%ld) success. ret = %d", - tt_gmt_nitz, ret); - } + tt_gmt_nitz -= ti->gmtoff * 60; +#endif - return TRUE; + return nitz_set_time(tt_gmt_nitz); } -static gboolean update_timezone(const struct tnoti_network_timeinfo *ti, - gboolean mode_auto) +static gboolean __update_timezone(const struct tnoti_network_timeinfo *ti, struct nitz_custom_data *data) { - int mcc; - char mcc_str[4]; - NITZ_MCC_TZFILE_MAP *m; + int mcc = -1; + char mcc_str[4] = {0,}; gboolean ret = FALSE; - snprintf(mcc_str, 4, "%s", ti->plmn); + memcpy(mcc_str, ti->plmn, 3); mcc = atoi(mcc_str); - dbg("MCC: [%d]", mcc); if (mcc >= 0) { - m = nitz_find_tzinfo(mcc, ti->gmtoff, ti->dstoff, ti->isdst); - if (m) { - dbg("Country: [%s] (ISO 3166)", m->country); - dbg("City: [%s]", m->city); - nitz_apply_tzfile(m->city, mode_auto); - ret = TRUE; - } else { - dbg("No search result"); - } + char *iso = __nitz_get_country_code_for_mcc(mcc_str, data); + ret = __update_timezone_by_offset(ti, iso); + g_free(iso); } return ret; } +GList *nitz_get_tzlist(char *iso, const struct tnoti_network_timeinfo *ti) +{ + char *timezone_name = 0; + UEnumeration *enum_tz = 0; + UErrorCode ec = U_ZERO_ERROR; + const UChar *timezone_id = 0; + int timezone_id_len = 0; + int offset = 0; + GList *tz_list = NULL; + + if (ti) { + offset = ti->gmtoff * 60 * 1000; + if (ti->isdst) + offset -= ti->dstoff * 60 * 60 * 1000; + dbg("offset = %d", offset); + enum_tz = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, iso, &offset, &ec); + } else { + enum_tz = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, iso, NULL, &ec); + } + + while (1) { + if (enum_tz == NULL) + break; + + timezone_id = uenum_unext(enum_tz, &timezone_id_len, &ec); + if (timezone_id == NULL) + break; + + timezone_name = (char *)g_malloc0(NITZ_TIMEZONE_MAX_LEN); + u_UCharsToChars(timezone_id, timezone_name, NITZ_TIMEZONE_MAX_LEN); + tz_list = g_list_append(tz_list, timezone_name); + info("[TIMESTAMP] ISO:[%s] offset:[%d], Available TZ:[%s]", iso, offset, timezone_name); + } + uenum_close(enum_tz); + return tz_list; +} + gboolean nitz_time_update(const struct tnoti_network_timeinfo *time_info, - gboolean mode_auto) + struct nitz_custom_data *data, gint delay) { + gboolean ret_time, ret_tz; + if (time_info->year == 0 && time_info->month == 0 && time_info->day == 0 && time_info->hour == 0 && time_info->minute == 0 && time_info->second == 0) { - /* Timezone only */ - return update_timezone(time_info, mode_auto); + /* + * Update Timezone only + */ + return __update_timezone(time_info, data); } - update_time(time_info, mode_auto); + /* + * Update (in order) - + * 1. Time + * 2. Timezone + */ + ret_time = __update_time(time_info, data, delay); + ret_tz = __update_timezone(time_info, data); - return update_timezone(time_info, mode_auto); + if (ret_time || ret_tz) + return TRUE; + else + return FALSE; } -- 2.34.1