Merge "Add InputMethodSubtype#getCanonicalizedLanguageTag()"

This commit is contained in:
Yohei Yukawa
2022-10-25 16:30:56 +00:00
committed by Android (Google) Code Review
2 changed files with 73 additions and 0 deletions

View File

@@ -16,6 +16,7 @@
package android.view.inputmethod;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -23,6 +24,7 @@ import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.icu.text.DisplayContext;
import android.icu.text.LocaleDisplayNames;
import android.icu.util.ULocale;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -89,6 +91,14 @@ public final class InputMethodSubtype implements Parcelable {
private volatile Locale mCachedLocaleObj;
private volatile HashMap<String, String> mExtraValueHashMapCache;
/**
* A volatile cache to optimize {@link #getCanonicalizedLanguageTag()}.
*
* <p>{@code null} means that the initial evaluation is not yet done.</p>
*/
@Nullable
private volatile String mCachedCanonicalizedLanguageTag;
/**
* InputMethodSubtypeBuilder is a builder class of InputMethodSubtype.
* This class is designed to be used with
@@ -391,6 +401,37 @@ public final class InputMethodSubtype implements Parcelable {
}
}
/**
* Returns a canonicalized BCP 47 Language Tag initialized with {@link #getLocaleObject()}.
*
* <p>This has an internal cache mechanism. Subsequent calls are in general cheap and fast.</p>
*
* @return a canonicalized BCP 47 Language Tag initialized with {@link #getLocaleObject()}. An
* empty string if {@link #getLocaleObject()} returns {@code null} or an empty
* {@link Locale} object.
* @hide
*/
@AnyThread
@NonNull
public String getCanonicalizedLanguageTag() {
final String cachedValue = mCachedCanonicalizedLanguageTag;
if (cachedValue != null) {
return cachedValue;
}
String result = null;
final Locale locale = getLocaleObject();
if (locale != null) {
final String langTag = locale.toLanguageTag();
if (!TextUtils.isEmpty(langTag)) {
result = ULocale.createCanonical(ULocale.forLanguageTag(langTag)).toLanguageTag();
}
}
result = TextUtils.emptyIfNull(result);
mCachedCanonicalizedLanguageTag = result;
return result;
}
/**
* @return The mode of the subtype.
*/

View File

@@ -20,8 +20,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import android.annotation.Nullable;
import android.os.Parcel;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
@@ -125,6 +127,36 @@ public class InputMethodSubtypeTest {
assertEquals("he", clonedSubtypeHe.getLocale());
}
@Test
public void testCanonicalizedLanguageTagObjectCache() {
final InputMethodSubtype subtype = createSubtypeUsingLanguageTag("en-US");
// Verify that the returned object is cached and any subsequent call should return the same
// object, which is strictly guaranteed if the method gets called only on a single thread.
assertSame(subtype.getCanonicalizedLanguageTag(), subtype.getCanonicalizedLanguageTag());
}
@Test
public void testCanonicalizedLanguageTag() {
verifyCanonicalizedLanguageTag("en", "en");
verifyCanonicalizedLanguageTag("en-US", "en-US");
verifyCanonicalizedLanguageTag("en-Latn-US-t-k0-qwerty", "en-Latn-US-t-k0-qwerty");
verifyCanonicalizedLanguageTag("en-us", "en-US");
verifyCanonicalizedLanguageTag("EN-us", "en-US");
verifyCanonicalizedLanguageTag(null, "");
verifyCanonicalizedLanguageTag("", "");
verifyCanonicalizedLanguageTag("und", "und");
verifyCanonicalizedLanguageTag("apparently invalid language tag!!!", "und");
}
private void verifyCanonicalizedLanguageTag(
@Nullable String languageTag, @Nullable String expectedLanguageTag) {
final InputMethodSubtype subtype = createSubtypeUsingLanguageTag(languageTag);
assertEquals(subtype.getCanonicalizedLanguageTag(), expectedLanguageTag);
}
private static InputMethodSubtype cloneViaParcel(final InputMethodSubtype original) {
Parcel parcel = null;
try {