1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.datetime.timezone.model; 17 18 import androidx.annotation.VisibleForTesting; 19 import androidx.collection.ArraySet; 20 21 import libcore.timezone.CountryTimeZones; 22 import libcore.timezone.CountryZonesFinder; 23 import libcore.timezone.TimeZoneFinder; 24 25 import java.lang.ref.WeakReference; 26 import java.util.Collections; 27 import java.util.HashSet; 28 import java.util.List; 29 import java.util.Locale; 30 import java.util.Set; 31 32 /** 33 * Wrapper of CountryZonesFinder to normalize the country code and only show the regions that are 34 * has time zone shown in the time zone picker. 35 * getInstance() reads the data from underlying file, and this means it should not be called 36 * from the UI thread. 37 */ 38 public class TimeZoneData { 39 40 private static WeakReference<TimeZoneData> sCache = null; 41 42 private final CountryZonesFinder mCountryZonesFinder; 43 private final Set<String> mRegionIds; 44 getInstance()45 public static synchronized TimeZoneData getInstance() { 46 TimeZoneData data = sCache == null ? null : sCache.get(); 47 if (data != null) { 48 return data; 49 } 50 data = new TimeZoneData(TimeZoneFinder.getInstance().getCountryZonesFinder()); 51 sCache = new WeakReference<>(data); 52 return data; 53 } 54 55 @VisibleForTesting TimeZoneData(CountryZonesFinder countryZonesFinder)56 public TimeZoneData(CountryZonesFinder countryZonesFinder) { 57 mCountryZonesFinder = countryZonesFinder; 58 mRegionIds = getNormalizedRegionIds(mCountryZonesFinder.lookupAllCountryIsoCodes()); 59 } 60 getRegionIds()61 public Set<String> getRegionIds() { 62 return mRegionIds; 63 } 64 lookupCountryCodesForZoneId(String tzId)65 public Set<String> lookupCountryCodesForZoneId(String tzId) { 66 if (tzId == null) { 67 return Collections.emptySet(); 68 } 69 List<CountryTimeZones> countryTimeZones = mCountryZonesFinder 70 .lookupCountryTimeZonesForZoneId(tzId); 71 Set<String> regionIds = new ArraySet<>(); 72 for (CountryTimeZones countryTimeZone : countryTimeZones) { 73 FilteredCountryTimeZones filteredZones = new FilteredCountryTimeZones(countryTimeZone); 74 if (filteredZones.getTimeZoneIds().contains(tzId)) { 75 regionIds.add(filteredZones.getRegionId()); 76 } 77 } 78 return regionIds; 79 } 80 lookupCountryTimeZones(String regionId)81 public FilteredCountryTimeZones lookupCountryTimeZones(String regionId) { 82 CountryTimeZones finder = regionId == null ? null 83 : mCountryZonesFinder.lookupCountryTimeZones(regionId); 84 return finder == null ? null : new FilteredCountryTimeZones(finder); 85 } 86 getNormalizedRegionIds(List<String> regionIds)87 private static Set<String> getNormalizedRegionIds(List<String> regionIds) { 88 final Set<String> result = new HashSet<>(regionIds.size()); 89 for (String regionId : regionIds) { 90 result.add(normalizeRegionId(regionId)); 91 } 92 return Collections.unmodifiableSet(result); 93 } 94 95 // Uppercase ASCII is normalized for the purpose of using ICU API normalizeRegionId(String regionId)96 public static String normalizeRegionId(String regionId) { 97 return regionId == null ? null : regionId.toUpperCase(Locale.US); 98 } 99 } 100