Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1484b9e7 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Add InputMethodSubtype#getCanonicalizedLanguageTag()

This is a preparation for implementing Subtype-keyed physical keyboard
layout switching.

This CL introduces an @hide method

   InputMethodSubtype#getCanonicalizedLanguageTag()

so that later CLs can be written by obtaining canonicalized BCP 47
Language Tags from InputMethodSubtype.

See test cases to see how it works.

Bug: 252816846
Test: atest FrameworksCoreTests:InputMethodSubtypeTest
Change-Id: I5276642ba83fb708e95591da9bc7fefe2810b170
parent b47dec6a
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -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.
     */
+32 −0
Original line number Diff line number Diff line
@@ -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 {