Merge "Fix ICU glue for uloc_toLanguageTag."
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index c869542..dc57b10 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -168,26 +168,28 @@
 static jstring ICU_languageTagForLocale(JNIEnv* env, jclass, jstring javaLocaleId) {
     ScopedUtfChars localeID(env, javaLocaleId);
 
-    // The conversion from an ICU locale ID to a BCP 47 tag will shrink
-    // the size of the string unless there's an invalid language or a bad
-    // parse (which will result in an x-lvariant private use subtag at
-    // the end of the input).
-    const size_t initialBufferSize = localeID.size();
+    // In most common cases, the BCP 47 tag will be the same size as the ICU
+    // locale ID
+    const size_t initialBufferSize = localeID.size() + 1;
     std::vector<char> buffer(initialBufferSize);
 
     UErrorCode status = U_ZERO_ERROR;
-    while (true) {
-        const size_t outputLength = uloc_toLanguageTag(localeID.c_str(),
-                &buffer[0], buffer.size(), false /* strict */, &status);
-        if (U_FAILURE(status)) {
-            return NULL;
-        }
+    const size_t outputLength = uloc_toLanguageTag(localeID.c_str(),
+            &buffer[0], buffer.size(), false /* strict */, &status);
+    if (status == U_BUFFER_OVERFLOW_ERROR) {
+        buffer.resize(outputLength + 1);
+        status = U_ZERO_ERROR;
+        uloc_toLanguageTag(localeID.c_str(), &buffer[0], buffer.size(),
+                false /* strict */, &status);
+    }
 
-        if (outputLength == buffer.size()) {
-            buffer.resize(buffer.size() << 1);
-        } else {
-            break;
-        }
+    if (status == U_STRING_NOT_TERMINATED_WARNING) {
+        buffer.resize(buffer.size() + 1);
+        buffer[buffer.size() -1] = '\0';
+    }
+
+    if (maybeThrowIcuException(env, "ICU::languageTagForLocale", status)) {
+        return NULL;
     }
 
     return env->NewStringUTF(&buffer[0]);
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index c6aea9e..89a64c7 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -1134,5 +1134,15 @@
         b.setLanguage("en").setExtension('x', "fooo-baar");
         assertEquals("en__#x-fooo-baar", b.build().toString());
     }
+
+    // Tests cases where our "guess" for the output size is incorrect.
+    //
+    // https://b.corp.google.com/issue?id=13414549
+    public void test_toLanguageTag_largerTag() {
+        Locale posix = new Locale.Builder()
+                .setLanguage("en").setRegion("US").setVariant("POSIX")
+                .build();
+        assertEquals("en-US-u-va-posix", posix.toLanguageTag());
+    }
 }