common: Add timezone library

Timezone is ported from Chromium.
Tracking /etc/localtime to know region and timezone.

BUG=b:63280507
TEST=emerge-${BOARD} arc-camera3-libcamera_timezone
CQ-DEPEND=CL:664500

Change-Id: I6aca1ee477c5d232145e3d78907d38a438f2b9cf
Reviewed-on: https://chromium-review.googlesource.com/650072
Commit-Ready: Heng-ruey Hsu <henryhsu@chromium.org>
Tested-by: Heng-ruey Hsu <henryhsu@chromium.org>
Reviewed-by: Ricky Liang <jcliang@chromium.org>
diff --git a/Makefile b/Makefile
index 9c07d31..a26fac5 100644
--- a/Makefile
+++ b/Makefile
@@ -49,6 +49,10 @@
 
 .PHONY: libcamera_jpeg
 
+libcamera_timezone: common/libcamera_timezone
+
+.PHONY: libcamera_timezone
+
 libcbm: common/libcbm
 
 .PHONY: libcbm
diff --git a/common/module.mk b/common/module.mk
index 9f2d5c1..5ba1d32 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -116,6 +116,19 @@
 clean: CLEAN(common/libcamera_exif.so)
 common/libcamera_exif: CXX_LIBRARY(common/libcamera_exif.so)
 
+libcamera_timezone_OBJS = common/timezone.o
+libcamera_timezone_PC_DEPS := libchrome-$(BASE_VER)
+libcamera_timezone_CPPFLAGS := \
+	$(call get_pc_cflags,$(libcamera_timezone_PC_DEPS))
+libcamera_timezone_LDLIBS := $(call get_pc_libs,$(libcamera_timezone_PC_DEPS))
+CXX_STATIC_LIBRARY(common/libcamera_timezone.pic.a): \
+	CPPFLAGS += $(libcamera_timezone_CPPFLAGS)
+CXX_STATIC_LIBRARY(common/libcamera_timezone.pic.a): \
+	LDLIBS += $(libcamera_timezone_LDLIBS)
+CXX_STATIC_LIBRARY(common/libcamera_timezone.pic.a): $(libcamera_timezone_OBJS)
+clean: CLEAN(common/libcamera_timezone.pic.a)
+common/libcamera_timezone: CXX_STATIC_LIBRARY(common/libcamera_timezone.pic.a)
+
 # To link against object files under common/, add $(COMMON_OBJECTS) to the
 # dependency list of your target.
 COMMON_OBJECTS := \
diff --git a/common/timezone.cc b/common/timezone.cc
new file mode 100644
index 0000000..58267ad
--- /dev/null
+++ b/common/timezone.cc
@@ -0,0 +1,654 @@
+/*
+ * Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "arc/timezone.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#include <map>
+
+#include <base/files/file_util.h>
+#include <base/macros.h>
+#include <base/memory/singleton.h>
+#include <base/strings/string16.h>
+#include <base/strings/utf_string_conversions.h>
+
+#include "arc/common.h"
+
+namespace arc {
+
+namespace {
+
+const char kTimeZoneFilePath[] = "/etc/localtime";
+const char kZoneInfoFilePath[] = "/usr/share/zoneinfo/";
+
+class TimezoneMap {
+ public:
+  static TimezoneMap* GetInstance() {
+    return base::Singleton<TimezoneMap>::get();
+  }
+
+  std::string CountryCodeForTimezone(const std::string& olson_code) {
+    std::map<const char*, const char*, CompareCStrings>::iterator iter =
+        map_.find(olson_code.c_str());
+    if (iter != map_.end())
+      return iter->second;
+
+    return std::string();
+  }
+
+ private:
+  TimezoneMap() {
+    // These mappings are adapted from zone.tab, which is available at
+    // <http://www.ietf.org/timezones/data/zone.tab> and is a part of public
+    // domain.
+    struct OlsonCodeData {
+      const char* country_code;
+      const char* olson_code;
+    };
+    static const OlsonCodeData olson_code_data[] = {
+        {"AD", "Europe/Andorra"},
+        {"AE", "Asia/Dubai"},
+        {"AF", "Asia/Kabul"},
+        {"AG", "America/Antigua"},
+        {"AI", "America/Anguilla"},
+        {"AL", "Europe/Tirane"},
+        {"AM", "Asia/Yerevan"},
+        {"AO", "Africa/Luanda"},
+        {"AQ", "Antarctica/McMurdo"},
+        {"AQ", "Antarctica/Rothera"},
+        {"AQ", "Antarctica/Palmer"},
+        {"AQ", "Antarctica/Mawson"},
+        {"AQ", "Antarctica/Davis"},
+        {"AQ", "Antarctica/Casey"},
+        {"AQ", "Antarctica/Vostok"},
+        {"AQ", "Antarctica/DumontDUrville"},
+        {"AQ", "Antarctica/Syowa"},
+        {"AR", "America/Argentina/Buenos_Aires"},
+        {"AR", "America/Argentina/Cordoba"},
+        {"AR", "America/Argentina/Salta"},
+        {"AR", "America/Argentina/Jujuy"},
+        {"AR", "America/Argentina/Tucuman"},
+        {"AR", "America/Argentina/Catamarca"},
+        {"AR", "America/Argentina/La_Rioja"},
+        {"AR", "America/Argentina/San_Juan"},
+        {"AR", "America/Argentina/Mendoza"},
+        {"AR", "America/Argentina/San_Luis"},
+        {"AR", "America/Argentina/Rio_Gallegos"},
+        {"AR", "America/Argentina/Ushuaia"},
+        {"AS", "Pacific/Pago_Pago"},
+        {"AT", "Europe/Vienna"},
+        {"AU", "Australia/Lord_Howe"},
+        {"AU", "Antarctica/Macquarie"},
+        {"AU", "Australia/Hobart"},
+        {"AU", "Australia/Currie"},
+        {"AU", "Australia/Melbourne"},
+        {"AU", "Australia/Sydney"},
+        {"AU", "Australia/Broken_Hill"},
+        {"AU", "Australia/Brisbane"},
+        {"AU", "Australia/Lindeman"},
+        {"AU", "Australia/Adelaide"},
+        {"AU", "Australia/Darwin"},
+        {"AU", "Australia/Perth"},
+        {"AU", "Australia/Eucla"},
+        {"AW", "America/Aruba"},
+        {"AX", "Europe/Mariehamn"},
+        {"AZ", "Asia/Baku"},
+        {"BA", "Europe/Sarajevo"},
+        {"BB", "America/Barbados"},
+        {"BD", "Asia/Dhaka"},
+        {"BE", "Europe/Brussels"},
+        {"BF", "Africa/Ouagadougou"},
+        {"BG", "Europe/Sofia"},
+        {"BH", "Asia/Bahrain"},
+        {"BI", "Africa/Bujumbura"},
+        {"BJ", "Africa/Porto-Novo"},
+        {"BL", "America/St_Barthelemy"},
+        {"BM", "Atlantic/Bermuda"},
+        {"BN", "Asia/Brunei"},
+        {"BO", "America/La_Paz"},
+        {"BQ", "America/Kralendijk"},
+        {"BR", "America/Noronha"},
+        {"BR", "America/Belem"},
+        {"BR", "America/Fortaleza"},
+        {"BR", "America/Recife"},
+        {"BR", "America/Araguaina"},
+        {"BR", "America/Maceio"},
+        {"BR", "America/Bahia"},
+        {"BR", "America/Sao_Paulo"},
+        {"BR", "America/Campo_Grande"},
+        {"BR", "America/Cuiaba"},
+        {"BR", "America/Santarem"},
+        {"BR", "America/Porto_Velho"},
+        {"BR", "America/Boa_Vista"},
+        {"BR", "America/Manaus"},
+        {"BR", "America/Eirunepe"},
+        {"BR", "America/Rio_Branco"},
+        {"BS", "America/Nassau"},
+        {"BT", "Asia/Thimphu"},
+        {"BW", "Africa/Gaborone"},
+        {"BY", "Europe/Minsk"},
+        {"BZ", "America/Belize"},
+        {"CA", "America/St_Johns"},
+        {"CA", "America/Halifax"},
+        {"CA", "America/Glace_Bay"},
+        {"CA", "America/Moncton"},
+        {"CA", "America/Goose_Bay"},
+        {"CA", "America/Blanc-Sablon"},
+        {"CA", "America/Toronto"},
+        {"CA", "America/Nipigon"},
+        {"CA", "America/Thunder_Bay"},
+        {"CA", "America/Iqaluit"},
+        {"CA", "America/Pangnirtung"},
+        {"CA", "America/Resolute"},
+        {"CA", "America/Atikokan"},
+        {"CA", "America/Rankin_Inlet"},
+        {"CA", "America/Winnipeg"},
+        {"CA", "America/Rainy_River"},
+        {"CA", "America/Regina"},
+        {"CA", "America/Swift_Current"},
+        {"CA", "America/Edmonton"},
+        {"CA", "America/Cambridge_Bay"},
+        {"CA", "America/Yellowknife"},
+        {"CA", "America/Inuvik"},
+        {"CA", "America/Creston"},
+        {"CA", "America/Dawson_Creek"},
+        {"CA", "America/Vancouver"},
+        {"CA", "America/Whitehorse"},
+        {"CA", "America/Dawson"},
+        {"CC", "Indian/Cocos"},
+        {"CD", "Africa/Kinshasa"},
+        {"CD", "Africa/Lubumbashi"},
+        {"CF", "Africa/Bangui"},
+        {"CG", "Africa/Brazzaville"},
+        {"CH", "Europe/Zurich"},
+        {"CI", "Africa/Abidjan"},
+        {"CK", "Pacific/Rarotonga"},
+        {"CL", "America/Santiago"},
+        {"CL", "Pacific/Easter"},
+        {"CM", "Africa/Douala"},
+        {"CN", "Asia/Shanghai"},
+        {"CN", "Asia/Harbin"},
+        {"CN", "Asia/Chongqing"},
+        {"CN", "Asia/Urumqi"},
+        {"CN", "Asia/Kashgar"},
+        {"CO", "America/Bogota"},
+        {"CR", "America/Costa_Rica"},
+        {"CU", "America/Havana"},
+        {"CV", "Atlantic/Cape_Verde"},
+        {"CW", "America/Curacao"},
+        {"CX", "Indian/Christmas"},
+        {"CY", "Asia/Nicosia"},
+        {"CZ", "Europe/Prague"},
+        {"DE", "Europe/Berlin"},
+        {"DE", "Europe/Busingen"},
+        {"DJ", "Africa/Djibouti"},
+        {"DK", "Europe/Copenhagen"},
+        {"DM", "America/Dominica"},
+        {"DO", "America/Santo_Domingo"},
+        {"DZ", "Africa/Algiers"},
+        {"EC", "America/Guayaquil"},
+        {"EC", "Pacific/Galapagos"},
+        {"EE", "Europe/Tallinn"},
+        {"EG", "Africa/Cairo"},
+        {"EH", "Africa/El_Aaiun"},
+        {"ER", "Africa/Asmara"},
+        {"ES", "Europe/Madrid"},
+        {"ES", "Africa/Ceuta"},
+        {"ES", "Atlantic/Canary"},
+        {"ET", "Africa/Addis_Ababa"},
+        {"FI", "Europe/Helsinki"},
+        {"FJ", "Pacific/Fiji"},
+        {"FK", "Atlantic/Stanley"},
+        {"FM", "Pacific/Chuuk"},
+        {"FM", "Pacific/Pohnpei"},
+        {"FM", "Pacific/Kosrae"},
+        {"FO", "Atlantic/Faroe"},
+        {"FR", "Europe/Paris"},
+        {"GA", "Africa/Libreville"},
+        {"GB", "Europe/London"},
+        {"GD", "America/Grenada"},
+        {"GE", "Asia/Tbilisi"},
+        {"GF", "America/Cayenne"},
+        {"GG", "Europe/Guernsey"},
+        {"GH", "Africa/Accra"},
+        {"GI", "Europe/Gibraltar"},
+        {"GL", "America/Godthab"},
+        {"GL", "America/Danmarkshavn"},
+        {"GL", "America/Scoresbysund"},
+        {"GL", "America/Thule"},
+        {"GM", "Africa/Banjul"},
+        {"GN", "Africa/Conakry"},
+        {"GP", "America/Guadeloupe"},
+        {"GQ", "Africa/Malabo"},
+        {"GR", "Europe/Athens"},
+        {"GS", "Atlantic/South_Georgia"},
+        {"GT", "America/Guatemala"},
+        {"GU", "Pacific/Guam"},
+        {"GW", "Africa/Bissau"},
+        {"GY", "America/Guyana"},
+        {"HK", "Asia/Hong_Kong"},
+        {"HN", "America/Tegucigalpa"},
+        {"HR", "Europe/Zagreb"},
+        {"HT", "America/Port-au-Prince"},
+        {"HU", "Europe/Budapest"},
+        {"ID", "Asia/Jakarta"},
+        {"ID", "Asia/Pontianak"},
+        {"ID", "Asia/Makassar"},
+        {"ID", "Asia/Jayapura"},
+        {"IE", "Europe/Dublin"},
+        {"IL", "Asia/Jerusalem"},
+        {"IM", "Europe/Isle_of_Man"},
+        {"IN", "Asia/Kolkata"},
+        {"IO", "Indian/Chagos"},
+        {"IQ", "Asia/Baghdad"},
+        {"IR", "Asia/Tehran"},
+        {"IS", "Atlantic/Reykjavik"},
+        {"IT", "Europe/Rome"},
+        {"JE", "Europe/Jersey"},
+        {"JM", "America/Jamaica"},
+        {"JO", "Asia/Amman"},
+        {"JP", "Asia/Tokyo"},
+        {"KE", "Africa/Nairobi"},
+        {"KG", "Asia/Bishkek"},
+        {"KH", "Asia/Phnom_Penh"},
+        {"KI", "Pacific/Tarawa"},
+        {"KI", "Pacific/Enderbury"},
+        {"KI", "Pacific/Kiritimati"},
+        {"KM", "Indian/Comoro"},
+        {"KN", "America/St_Kitts"},
+        {"KP", "Asia/Pyongyang"},
+        {"KR", "Asia/Seoul"},
+        {"KW", "Asia/Kuwait"},
+        {"KY", "America/Cayman"},
+        {"KZ", "Asia/Almaty"},
+        {"KZ", "Asia/Qyzylorda"},
+        {"KZ", "Asia/Aqtobe"},
+        {"KZ", "Asia/Aqtau"},
+        {"KZ", "Asia/Oral"},
+        {"LA", "Asia/Vientiane"},
+        {"LB", "Asia/Beirut"},
+        {"LC", "America/St_Lucia"},
+        {"LI", "Europe/Vaduz"},
+        {"LK", "Asia/Colombo"},
+        {"LR", "Africa/Monrovia"},
+        {"LS", "Africa/Maseru"},
+        {"LT", "Europe/Vilnius"},
+        {"LU", "Europe/Luxembourg"},
+        {"LV", "Europe/Riga"},
+        {"LY", "Africa/Tripoli"},
+        {"MA", "Africa/Casablanca"},
+        {"MC", "Europe/Monaco"},
+        {"MD", "Europe/Chisinau"},
+        {"ME", "Europe/Podgorica"},
+        {"MF", "America/Marigot"},
+        {"MG", "Indian/Antananarivo"},
+        {"MH", "Pacific/Majuro"},
+        {"MH", "Pacific/Kwajalein"},
+        {"MK", "Europe/Skopje"},
+        {"ML", "Africa/Bamako"},
+        {"MM", "Asia/Rangoon"},
+        {"MN", "Asia/Ulaanbaatar"},
+        {"MN", "Asia/Hovd"},
+        {"MN", "Asia/Choibalsan"},
+        {"MO", "Asia/Macau"},
+        {"MP", "Pacific/Saipan"},
+        {"MQ", "America/Martinique"},
+        {"MR", "Africa/Nouakchott"},
+        {"MS", "America/Montserrat"},
+        {"MT", "Europe/Malta"},
+        {"MU", "Indian/Mauritius"},
+        {"MV", "Indian/Maldives"},
+        {"MW", "Africa/Blantyre"},
+        {"MX", "America/Mexico_City"},
+        {"MX", "America/Cancun"},
+        {"MX", "America/Merida"},
+        {"MX", "America/Monterrey"},
+        {"MX", "America/Matamoros"},
+        {"MX", "America/Mazatlan"},
+        {"MX", "America/Chihuahua"},
+        {"MX", "America/Ojinaga"},
+        {"MX", "America/Hermosillo"},
+        {"MX", "America/Tijuana"},
+        {"MX", "America/Santa_Isabel"},
+        {"MX", "America/Bahia_Banderas"},
+        {"MY", "Asia/Kuala_Lumpur"},
+        {"MY", "Asia/Kuching"},
+        {"MZ", "Africa/Maputo"},
+        {"NA", "Africa/Windhoek"},
+        {"NC", "Pacific/Noumea"},
+        {"NE", "Africa/Niamey"},
+        {"NF", "Pacific/Norfolk"},
+        {"NG", "Africa/Lagos"},
+        {"NI", "America/Managua"},
+        {"NL", "Europe/Amsterdam"},
+        {"NO", "Europe/Oslo"},
+        {"NP", "Asia/Kathmandu"},
+        {"NR", "Pacific/Nauru"},
+        {"NU", "Pacific/Niue"},
+        {"NZ", "Pacific/Auckland"},
+        {"NZ", "Pacific/Chatham"},
+        {"OM", "Asia/Muscat"},
+        {"PA", "America/Panama"},
+        {"PE", "America/Lima"},
+        {"PF", "Pacific/Tahiti"},
+        {"PF", "Pacific/Marquesas"},
+        {"PF", "Pacific/Gambier"},
+        {"PG", "Pacific/Port_Moresby"},
+        {"PH", "Asia/Manila"},
+        {"PK", "Asia/Karachi"},
+        {"PL", "Europe/Warsaw"},
+        {"PM", "America/Miquelon"},
+        {"PN", "Pacific/Pitcairn"},
+        {"PR", "America/Puerto_Rico"},
+        {"PS", "Asia/Gaza"},
+        {"PS", "Asia/Hebron"},
+        {"PT", "Europe/Lisbon"},
+        {"PT", "Atlantic/Madeira"},
+        {"PT", "Atlantic/Azores"},
+        {"PW", "Pacific/Palau"},
+        {"PY", "America/Asuncion"},
+        {"QA", "Asia/Qatar"},
+        {"RE", "Indian/Reunion"},
+        {"RO", "Europe/Bucharest"},
+        {"RS", "Europe/Belgrade"},
+        {"RU", "Europe/Kaliningrad"},
+        {"RU", "Europe/Moscow"},
+        {"RU", "Europe/Volgograd"},
+        {"RU", "Europe/Samara"},
+        {"RU", "Asia/Yekaterinburg"},
+        {"RU", "Asia/Omsk"},
+        {"RU", "Asia/Novosibirsk"},
+        {"RU", "Asia/Novokuznetsk"},
+        {"RU", "Asia/Krasnoyarsk"},
+        {"RU", "Asia/Irkutsk"},
+        {"RU", "Asia/Yakutsk"},
+        {"RU", "Asia/Khandyga"},
+        {"RU", "Asia/Vladivostok"},
+        {"RU", "Asia/Sakhalin"},
+        {"RU", "Asia/Ust-Nera"},
+        {"RU", "Asia/Magadan"},
+        {"RU", "Asia/Kamchatka"},
+        {"RU", "Asia/Anadyr"},
+        {"RW", "Africa/Kigali"},
+        {"SA", "Asia/Riyadh"},
+        {"SB", "Pacific/Guadalcanal"},
+        {"SC", "Indian/Mahe"},
+        {"SD", "Africa/Khartoum"},
+        {"SE", "Europe/Stockholm"},
+        {"SG", "Asia/Singapore"},
+        {"SH", "Atlantic/St_Helena"},
+        {"SI", "Europe/Ljubljana"},
+        {"SJ", "Arctic/Longyearbyen"},
+        {"SK", "Europe/Bratislava"},
+        {"SL", "Africa/Freetown"},
+        {"SM", "Europe/San_Marino"},
+        {"SN", "Africa/Dakar"},
+        {"SO", "Africa/Mogadishu"},
+        {"SR", "America/Paramaribo"},
+        {"SS", "Africa/Juba"},
+        {"ST", "Africa/Sao_Tome"},
+        {"SV", "America/El_Salvador"},
+        {"SX", "America/Lower_Princes"},
+        {"SY", "Asia/Damascus"},
+        {"SZ", "Africa/Mbabane"},
+        {"TC", "America/Grand_Turk"},
+        {"TD", "Africa/Ndjamena"},
+        {"TF", "Indian/Kerguelen"},
+        {"TG", "Africa/Lome"},
+        {"TH", "Asia/Bangkok"},
+        {"TJ", "Asia/Dushanbe"},
+        {"TK", "Pacific/Fakaofo"},
+        {"TL", "Asia/Dili"},
+        {"TM", "Asia/Ashgabat"},
+        {"TN", "Africa/Tunis"},
+        {"TO", "Pacific/Tongatapu"},
+        {"TR", "Europe/Istanbul"},
+        {"TT", "America/Port_of_Spain"},
+        {"TV", "Pacific/Funafuti"},
+        {"TW", "Asia/Taipei"},
+        {"TZ", "Africa/Dar_es_Salaam"},
+        {"UA", "Europe/Kiev"},
+        {"UA", "Europe/Uzhgorod"},
+        {"UA", "Europe/Zaporozhye"},
+        {"UA", "Europe/Simferopol"},
+        {"UG", "Africa/Kampala"},
+        {"UM", "Pacific/Johnston"},
+        {"UM", "Pacific/Midway"},
+        {"UM", "Pacific/Wake"},
+        {"US", "America/New_York"},
+        {"US", "America/Detroit"},
+        {"US", "America/Kentucky/Louisville"},
+        {"US", "America/Kentucky/Monticello"},
+        {"US", "America/Indiana/Indianapolis"},
+        {"US", "America/Indiana/Vincennes"},
+        {"US", "America/Indiana/Winamac"},
+        {"US", "America/Indiana/Marengo"},
+        {"US", "America/Indiana/Petersburg"},
+        {"US", "America/Indiana/Vevay"},
+        {"US", "America/Chicago"},
+        {"US", "America/Indiana/Tell_City"},
+        {"US", "America/Indiana/Knox"},
+        {"US", "America/Menominee"},
+        {"US", "America/North_Dakota/Center"},
+        {"US", "America/North_Dakota/New_Salem"},
+        {"US", "America/North_Dakota/Beulah"},
+        {"US", "America/Denver"},
+        {"US", "America/Boise"},
+        {"US", "America/Phoenix"},
+        {"US", "America/Los_Angeles"},
+        {"US", "America/Anchorage"},
+        {"US", "America/Juneau"},
+        {"US", "America/Sitka"},
+        {"US", "America/Yakutat"},
+        {"US", "America/Nome"},
+        {"US", "America/Adak"},
+        {"US", "America/Metlakatla"},
+        {"US", "Pacific/Honolulu"},
+        {"UY", "America/Montevideo"},
+        {"UZ", "Asia/Samarkand"},
+        {"UZ", "Asia/Tashkent"},
+        {"VA", "Europe/Vatican"},
+        {"VC", "America/St_Vincent"},
+        {"VE", "America/Caracas"},
+        {"VG", "America/Tortola"},
+        {"VI", "America/St_Thomas"},
+        {"VN", "Asia/Ho_Chi_Minh"},
+        {"VU", "Pacific/Efate"},
+        {"WF", "Pacific/Wallis"},
+        {"WS", "Pacific/Apia"},
+        {"YE", "Asia/Aden"},
+        {"YT", "Indian/Mayotte"},
+        {"ZA", "Africa/Johannesburg"},
+        {"ZM", "Africa/Lusaka"},
+        {"ZW", "Africa/Harare"},
+        // The mappings below are custom additions to zone.tab.
+        {"GB", "Etc/GMT"},
+        {"GB", "Etc/UTC"},
+        {"GB", "Etc/UCT"},
+    };
+
+    for (size_t i = 0; i < arraysize(olson_code_data); ++i)
+      map_[olson_code_data[i].olson_code] = olson_code_data[i].country_code;
+
+    // These are mapping from old codenames to new codenames. They are also
+    // part of public domain, and available at
+    // <http://www.ietf.org/timezones/data/backward>.
+    struct LinkData {
+      const char* old_code;
+      const char* new_code;
+    };
+    static const LinkData link_data[] = {
+        {"Africa/Asmera", "Africa/Asmara"},
+        {"Africa/Timbuktu", "Africa/Bamako"},
+        {"America/Argentina/ComodRivadavia", "America/Argentina/Catamarca"},
+        {"America/Atka", "America/Adak"},
+        {"America/Buenos_Aires", "America/Argentina/Buenos_Aires"},
+        {"America/Catamarca", "America/Argentina/Catamarca"},
+        {"America/Coral_Harbour", "America/Atikokan"},
+        {"America/Cordoba", "America/Argentina/Cordoba"},
+        {"America/Ensenada", "America/Tijuana"},
+        {"America/Fort_Wayne", "America/Indiana/Indianapolis"},
+        {"America/Indianapolis", "America/Indiana/Indianapolis"},
+        {"America/Jujuy", "America/Argentina/Jujuy"},
+        {"America/Knox_IN", "America/Indiana/Knox"},
+        {"America/Louisville", "America/Kentucky/Louisville"},
+        {"America/Mendoza", "America/Argentina/Mendoza"},
+        {"America/Porto_Acre", "America/Rio_Branco"},
+        {"America/Rosario", "America/Argentina/Cordoba"},
+        {"America/Virgin", "America/St_Thomas"},
+        {"Asia/Ashkhabad", "Asia/Ashgabat"},
+        {"Asia/Chungking", "Asia/Chongqing"},
+        {"Asia/Dacca", "Asia/Dhaka"},
+        {"Asia/Katmandu", "Asia/Kathmandu"},
+        {"Asia/Calcutta", "Asia/Kolkata"},
+        {"Asia/Macao", "Asia/Macau"},
+        {"Asia/Tel_Aviv", "Asia/Jerusalem"},
+        {"Asia/Saigon", "Asia/Ho_Chi_Minh"},
+        {"Asia/Thimbu", "Asia/Thimphu"},
+        {"Asia/Ujung_Pandang", "Asia/Makassar"},
+        {"Asia/Ulan_Bator", "Asia/Ulaanbaatar"},
+        {"Atlantic/Faeroe", "Atlantic/Faroe"},
+        {"Atlantic/Jan_Mayen", "Europe/Oslo"},
+        {"Australia/ACT", "Australia/Sydney"},
+        {"Australia/Canberra", "Australia/Sydney"},
+        {"Australia/LHI", "Australia/Lord_Howe"},
+        {"Australia/NSW", "Australia/Sydney"},
+        {"Australia/North", "Australia/Darwin"},
+        {"Australia/Queensland", "Australia/Brisbane"},
+        {"Australia/South", "Australia/Adelaide"},
+        {"Australia/Tasmania", "Australia/Hobart"},
+        {"Australia/Victoria", "Australia/Melbourne"},
+        {"Australia/West", "Australia/Perth"},
+        {"Australia/Yancowinna", "Australia/Broken_Hill"},
+        {"Brazil/Acre", "America/Rio_Branco"},
+        {"Brazil/DeNoronha", "America/Noronha"},
+        {"Brazil/East", "America/Sao_Paulo"},
+        {"Brazil/West", "America/Manaus"},
+        {"Canada/Atlantic", "America/Halifax"},
+        {"Canada/Central", "America/Winnipeg"},
+        {"Canada/East-Saskatchewan", "America/Regina"},
+        {"Canada/Eastern", "America/Toronto"},
+        {"Canada/Mountain", "America/Edmonton"},
+        {"Canada/Newfoundland", "America/St_Johns"},
+        {"Canada/Pacific", "America/Vancouver"},
+        {"Canada/Saskatchewan", "America/Regina"},
+        {"Canada/Yukon", "America/Whitehorse"},
+        {"Chile/Continental", "America/Santiago"},
+        {"Chile/EasterIsland", "Pacific/Easter"},
+        {"Cuba", "America/Havana"},
+        {"Egypt", "Africa/Cairo"},
+        {"Eire", "Europe/Dublin"},
+        {"Europe/Belfast", "Europe/London"},
+        {"Europe/Tiraspol", "Europe/Chisinau"},
+        {"GB", "Europe/London"},
+        {"GB-Eire", "Europe/London"},
+        {"GMT+0", "Etc/GMT"},
+        {"GMT-0", "Etc/GMT"},
+        {"GMT0", "Etc/GMT"},
+        {"Greenwich", "Etc/GMT"},
+        {"Hongkong", "Asia/Hong_Kong"},
+        {"Iceland", "Atlantic/Reykjavik"},
+        {"Iran", "Asia/Tehran"},
+        {"Israel", "Asia/Jerusalem"},
+        {"Jamaica", "America/Jamaica"},
+        {"Japan", "Asia/Tokyo"},
+        {"Kwajalein", "Pacific/Kwajalein"},
+        {"Libya", "Africa/Tripoli"},
+        {"Mexico/BajaNorte", "America/Tijuana"},
+        {"Mexico/BajaSur", "America/Mazatlan"},
+        {"Mexico/General", "America/Mexico_City"},
+        {"NZ", "Pacific/Auckland"},
+        {"NZ-CHAT", "Pacific/Chatham"},
+        {"Navajo", "America/Denver"},
+        {"PRC", "Asia/Shanghai"},
+        {"Pacific/Samoa", "Pacific/Pago_Pago"},
+        {"Pacific/Yap", "Pacific/Chuuk"},
+        {"Pacific/Truk", "Pacific/Chuuk"},
+        {"Pacific/Ponape", "Pacific/Pohnpei"},
+        {"Poland", "Europe/Warsaw"},
+        {"Portugal", "Europe/Lisbon"},
+        {"ROC", "Asia/Taipei"},
+        {"ROK", "Asia/Seoul"},
+        {"Singapore", "Asia/Singapore"},
+        {"Turkey", "Europe/Istanbul"},
+        {"UCT", "Etc/UCT"},
+        {"US/Alaska", "America/Anchorage"},
+        {"US/Aleutian", "America/Adak"},
+        {"US/Arizona", "America/Phoenix"},
+        {"US/Central", "America/Chicago"},
+        {"US/East-Indiana", "America/Indiana/Indianapolis"},
+        {"US/Eastern", "America/New_York"},
+        {"US/Hawaii", "Pacific/Honolulu"},
+        {"US/Indiana-Starke", "America/Indiana/Knox"},
+        {"US/Michigan", "America/Detroit"},
+        {"US/Mountain", "America/Denver"},
+        {"US/Pacific", "America/Los_Angeles"},
+        {"US/Samoa", "Pacific/Pago_Pago"},
+        {"UTC", "Etc/UTC"},
+        {"Universal", "Etc/UTC"},
+        {"W-SU", "Europe/Moscow"},
+        {"Zulu", "Etc/UTC"},
+    };
+
+    for (size_t i = 0; i < arraysize(link_data); ++i)
+      map_[link_data[i].old_code] = map_[link_data[i].new_code];
+  }
+
+  friend struct base::DefaultSingletonTraits<TimezoneMap>;
+
+  struct CompareCStrings {
+    bool operator()(const char* str1, const char* str2) const {
+      return strcmp(str1, str2) < 0;
+    }
+  };
+  std::map<const char*, const char*, CompareCStrings> map_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimezoneMap);
+};
+
+}  // namespace
+
+std::string CountryCodeForCurrentTimezone() {
+  base::FilePath target;
+  base::FilePath timezone_path(kTimeZoneFilePath);
+  while (base::ReadSymbolicLink(timezone_path, &target)) {
+    timezone_path = base::FilePath(target);
+  }
+  if (timezone_path.value().compare(0, strlen(kZoneInfoFilePath),
+                                    kZoneInfoFilePath)) {
+    LOGF(WARNING) << "Timezone is unknown. Anti banding may be broken.";
+    return std::string();
+  }
+  std::string olson_code = timezone_path.value();
+  olson_code.replace(0, strlen(kZoneInfoFilePath), "");
+  LOGF(INFO) << "Timezone: " << olson_code;
+  return TimezoneMap::GetInstance()->CountryCodeForTimezone(olson_code);
+}
+
+PowerLineFrequency GetPowerLineFrequencyForLocation() {
+  const std::string current_country = CountryCodeForCurrentTimezone();
+  if (current_country.empty())
+    return PowerLineFrequency::FREQ_DEFAULT;
+  LOGF(INFO) << "Country: " << current_country;
+  // Sorted out list of countries with 60Hz power line frequency, from
+  // http://en.wikipedia.org/wiki/Mains_electricity_by_country
+  const char* countries_using_60Hz[] = {
+      "AI", "AO", "AS", "AW", "AZ", "BM", "BR", "BS", "BZ", "CA", "CO",
+      "CR", "CU", "DO", "EC", "FM", "GT", "GU", "GY", "HN", "HT", "JP",
+      "KN", "KR", "KY", "MS", "MX", "NI", "PA", "PE", "PF", "PH", "PR",
+      "PW", "SA", "SR", "SV", "TT", "TW", "UM", "US", "VG", "VI", "VE"};
+  const char** countries_using_60Hz_end =
+      countries_using_60Hz + arraysize(countries_using_60Hz);
+  if (std::find(countries_using_60Hz, countries_using_60Hz_end,
+                current_country) == countries_using_60Hz_end) {
+    return PowerLineFrequency::FREQ_50HZ;
+  }
+  return PowerLineFrequency::FREQ_60HZ;
+}
+
+}  // namespace arc
diff --git a/include/arc/timezone.h b/include/arc/timezone.h
new file mode 100644
index 0000000..90f2cce
--- /dev/null
+++ b/include/arc/timezone.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef INCLUDE_ARC_TIMEZONE_H_
+#define INCLUDE_ARC_TIMEZONE_H_
+
+#include <string>
+
+namespace arc {
+
+enum class PowerLineFrequency {
+  FREQ_DEFAULT = 0,
+  FREQ_50HZ = 1,
+  FREQ_60HZ = 2,
+  FREQ_AUTO = 3,
+  FREQ_ERROR = 4,
+};
+
+// Checks the system timezone and turns it into a two-character ASCII country
+// code. This may fail (for example, it will always fail on Android), in which
+// case it will return an empty string.
+std::string CountryCodeForCurrentTimezone();
+
+// Queries timezone to know the country to decide power frequency to do
+// anti-banding.
+PowerLineFrequency GetPowerLineFrequencyForLocation();
+
+}  // namespace arc
+
+#endif  // INCLUDE_ARC_TIMEZONE_H_