1/* 2 * Copyright (C) 2010 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 17#define LOG_TAG "TimeZoneNames" 18 19#include <memory> 20 21#include <nativehelper/JNIHelp.h> 22#include <nativehelper/JniConstants.h> 23#include <nativehelper/ScopedLocalRef.h> 24#include <nativehelper/ScopedUtfChars.h> 25 26#include "IcuUtilities.h" 27#include "JniException.h" 28#include "ScopedIcuLocale.h" 29#include "ScopedJavaUnicodeString.h" 30#include "unicode/calendar.h" 31#include "unicode/timezone.h" 32#include "unicode/tznames.h" 33 34static bool setStringArrayElement(JNIEnv* env, jobjectArray array, int i, const icu::UnicodeString& s) { 35 // Don't use "GMT" string, for backwards compatibility. 36 static const icu::UnicodeString kGmt("GMT", 3, US_INV); 37 if (!s.isBogus() && !s.startsWith(kGmt)) { 38 ScopedLocalRef<jstring> javaString(env, jniCreateString(env, s.getBuffer(), s.length())); 39 if (javaString.get() == NULL) { 40 return false; 41 } 42 env->SetObjectArrayElement(array, i, javaString.get()); 43 } 44 return true; 45} 46 47static void TimeZoneNames_fillZoneStrings(JNIEnv* env, jclass, jstring javaLocaleName, jobjectArray result) { 48 ScopedIcuLocale icuLocale(env, javaLocaleName); 49 if (!icuLocale.valid()) { 50 return; 51 } 52 53 UErrorCode status = U_ZERO_ERROR; 54 std::unique_ptr<icu::TimeZoneNames> names(icu::TimeZoneNames::createInstance(icuLocale.locale(), status)); 55 if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) { 56 return; 57 } 58 59 const UDate now(icu::Calendar::getNow()); 60 61 size_t id_count = env->GetArrayLength(result); 62 for (size_t i = 0; i < id_count; ++i) { 63 ScopedLocalRef<jobjectArray> java_row(env, 64 reinterpret_cast<jobjectArray>(env->GetObjectArrayElement(result, i))); 65 ScopedLocalRef<jstring> java_zone_id(env, 66 reinterpret_cast<jstring>(env->GetObjectArrayElement(java_row.get(), 0))); 67 ScopedJavaUnicodeString zone_id(env, java_zone_id.get()); 68 if (!zone_id.valid()) { 69 return; 70 } 71 72 // Canonicalize the zone ID to the one known by ICU. 73 icu::UnicodeString lookup_id; 74 icu::TimeZone::getCanonicalID(zone_id.unicodeString(), lookup_id, status); 75 if (status != U_ZERO_ERROR) { 76 // Unknown ID - just use the zone ID we have. 77 lookup_id = zone_id.unicodeString(); 78 } 79 80 icu::UnicodeString long_std; 81 names->getDisplayName(lookup_id, UTZNM_LONG_STANDARD, now, long_std); 82 icu::UnicodeString short_std; 83 names->getDisplayName(lookup_id, UTZNM_SHORT_STANDARD, now, short_std); 84 icu::UnicodeString long_dst; 85 names->getDisplayName(lookup_id, UTZNM_LONG_DAYLIGHT, now, long_dst); 86 icu::UnicodeString short_dst; 87 names->getDisplayName(lookup_id, UTZNM_SHORT_DAYLIGHT, now, short_dst); 88 89 bool okay = 90 setStringArrayElement(env, java_row.get(), 1, long_std) && 91 setStringArrayElement(env, java_row.get(), 2, short_std) && 92 setStringArrayElement(env, java_row.get(), 3, long_dst) && 93 setStringArrayElement(env, java_row.get(), 4, short_dst); 94 if (!okay) { 95 return; 96 } 97 } 98} 99 100static JNINativeMethod gMethods[] = { 101 NATIVE_METHOD(TimeZoneNames, fillZoneStrings, "(Ljava/lang/String;[[Ljava/lang/String;)V"), 102}; 103void register_libcore_icu_TimeZoneNames(JNIEnv* env) { 104 jniRegisterNativeMethods(env, "libcore/icu/TimeZoneNames", gMethods, NELEM(gMethods)); 105} 106