Merge "Modify Script matching algorithm" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
cbb43d662a
@@ -1261,30 +1261,45 @@ final class KeyboardLayoutManager implements InputManager.InputDeviceListener {
|
|||||||
|
|
||||||
private static boolean isLayoutCompatibleWithLanguageTag(KeyboardLayout layout,
|
private static boolean isLayoutCompatibleWithLanguageTag(KeyboardLayout layout,
|
||||||
@NonNull String languageTag) {
|
@NonNull String languageTag) {
|
||||||
final int[] scriptsFromLanguageTag = UScript.getCode(Locale.forLanguageTag(languageTag));
|
LocaleList layoutLocales = layout.getLocales();
|
||||||
if (scriptsFromLanguageTag.length == 0) {
|
if (layoutLocales.isEmpty()) {
|
||||||
// If no scripts inferred from languageTag then allowing the layout
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
LocaleList locales = layout.getLocales();
|
|
||||||
if (locales.isEmpty()) {
|
|
||||||
// KCM file doesn't have an associated language tag. This can be from
|
// KCM file doesn't have an associated language tag. This can be from
|
||||||
// a 3rd party app so need to include it as a potential layout.
|
// a 3rd party app so need to include it as a potential layout.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < locales.size(); i++) {
|
// Match derived Script codes
|
||||||
final Locale locale = locales.get(i);
|
final int[] scriptsFromLanguageTag = getScriptCodes(Locale.forLanguageTag(languageTag));
|
||||||
if (locale == null) {
|
if (scriptsFromLanguageTag.length == 0) {
|
||||||
continue;
|
// If no scripts inferred from languageTag then allowing the layout
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
int[] scripts = UScript.getCode(locale);
|
for (int i = 0; i < layoutLocales.size(); i++) {
|
||||||
if (scripts != null && haveCommonValue(scripts, scriptsFromLanguageTag)) {
|
final Locale locale = layoutLocales.get(i);
|
||||||
|
int[] scripts = getScriptCodes(locale);
|
||||||
|
if (haveCommonValue(scripts, scriptsFromLanguageTag)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int[] getScriptCodes(@Nullable Locale locale) {
|
||||||
|
if (locale == null) {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
if (!TextUtils.isEmpty(locale.getScript())) {
|
||||||
|
int scriptCode = UScript.getCodeFromName(locale.getScript());
|
||||||
|
if (scriptCode != UScript.INVALID_CODE) {
|
||||||
|
return new int[]{scriptCode};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int[] scripts = UScript.getCode(locale);
|
||||||
|
if (scripts != null) {
|
||||||
|
return scripts;
|
||||||
|
}
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean haveCommonValue(int[] arr1, int[] arr2) {
|
private static boolean haveCommonValue(int[] arr1, int[] arr2) {
|
||||||
for (int a1 : arr1) {
|
for (int a1 : arr1) {
|
||||||
for (int a2 : arr2) {
|
for (int a2 : arr2) {
|
||||||
|
|||||||
@@ -72,10 +72,18 @@
|
|||||||
android:keyboardLayout="@raw/dummy_keyboard_layout"
|
android:keyboardLayout="@raw/dummy_keyboard_layout"
|
||||||
android:keyboardLocale="ru-Cyrl" />
|
android:keyboardLocale="ru-Cyrl" />
|
||||||
|
|
||||||
|
<keyboard-layout
|
||||||
|
android:name="keyboard_layout_english_without_script_code"
|
||||||
|
android:label="English(No script code)"
|
||||||
|
android:keyboardLayout="@raw/dummy_keyboard_layout"
|
||||||
|
android:keyboardLocale="en"
|
||||||
|
android:keyboardLayoutType="qwerty" />
|
||||||
|
|
||||||
<keyboard-layout
|
<keyboard-layout
|
||||||
android:name="keyboard_layout_vendorId:1,productId:1"
|
android:name="keyboard_layout_vendorId:1,productId:1"
|
||||||
android:label="vendorId:1,productId:1"
|
android:label="vendorId:1,productId:1"
|
||||||
android:keyboardLayout="@raw/dummy_keyboard_layout"
|
android:keyboardLayout="@raw/dummy_keyboard_layout"
|
||||||
androidprv:vendorId="1"
|
androidprv:vendorId="1"
|
||||||
androidprv:productId="1" />
|
androidprv:productId="1" />
|
||||||
|
|
||||||
</keyboard-layouts>
|
</keyboard-layouts>
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import android.content.pm.ServiceInfo
|
|||||||
import android.hardware.input.IInputManager
|
import android.hardware.input.IInputManager
|
||||||
import android.hardware.input.InputManager
|
import android.hardware.input.InputManager
|
||||||
import android.hardware.input.KeyboardLayout
|
import android.hardware.input.KeyboardLayout
|
||||||
import android.icu.lang.UScript
|
|
||||||
import android.icu.util.ULocale
|
import android.icu.util.ULocale
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.test.TestLooper
|
import android.os.test.TestLooper
|
||||||
@@ -52,7 +51,6 @@ import java.io.FileNotFoundException
|
|||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
private fun createKeyboard(
|
private fun createKeyboard(
|
||||||
deviceId: Int,
|
deviceId: Int,
|
||||||
@@ -553,24 +551,17 @@ class KeyboardLayoutManagerTests {
|
|||||||
0,
|
0,
|
||||||
keyboardLayouts.size
|
keyboardLayouts.size
|
||||||
)
|
)
|
||||||
|
assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
|
||||||
val englishScripts = UScript.getCode(Locale.forLanguageTag("hi-Latn"))
|
"containing English(US) layout for hi-Latn",
|
||||||
for (kl in keyboardLayouts) {
|
containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
|
||||||
var isCompatible = false
|
)
|
||||||
for (i in 0 until kl.locales.size()) {
|
assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
|
||||||
val locale: Locale = kl.locales.get(i) ?: continue
|
"containing English(No script code) layout for hi-Latn",
|
||||||
val scripts = UScript.getCode(locale)
|
containsLayout(
|
||||||
if (scripts != null && areScriptsCompatible(scripts, englishScripts)) {
|
keyboardLayouts,
|
||||||
isCompatible = true
|
createLayoutDescriptor("keyboard_layout_english_without_script_code")
|
||||||
break
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
assertTrue(
|
|
||||||
"New UI: getKeyboardLayoutListForInputDevice API should only return " +
|
|
||||||
"compatible layouts but found " + kl.descriptor,
|
|
||||||
isCompatible
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
// Check Layouts for "hi" which by default uses 'Deva' script.
|
// Check Layouts for "hi" which by default uses 'Deva' script.
|
||||||
keyboardLayouts =
|
keyboardLayouts =
|
||||||
@@ -600,6 +591,46 @@ class KeyboardLayoutManagerTests {
|
|||||||
1,
|
1,
|
||||||
keyboardLayouts.size
|
keyboardLayouts.size
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Special case Japanese: UScript ignores provided script code for certain language tags
|
||||||
|
// Should manually match provided script codes and then rely on Uscript to derive
|
||||||
|
// script from language tags and match those.
|
||||||
|
keyboardLayouts =
|
||||||
|
keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
|
||||||
|
keyboardDevice.identifier, USER_ID, imeInfo,
|
||||||
|
createImeSubtypeForLanguageTag("ja-Latn-JP")
|
||||||
|
)
|
||||||
|
assertNotEquals(
|
||||||
|
"New UI: getKeyboardLayoutListForInputDevice API should return the list of " +
|
||||||
|
"supported layouts with matching script code for ja-Latn-JP",
|
||||||
|
0,
|
||||||
|
keyboardLayouts.size
|
||||||
|
)
|
||||||
|
assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
|
||||||
|
"containing English(US) layout for ja-Latn-JP",
|
||||||
|
containsLayout(keyboardLayouts, ENGLISH_US_LAYOUT_DESCRIPTOR)
|
||||||
|
)
|
||||||
|
assertTrue("New UI: getKeyboardLayoutListForInputDevice API should return a list " +
|
||||||
|
"containing English(No script code) layout for ja-Latn-JP",
|
||||||
|
containsLayout(
|
||||||
|
keyboardLayouts,
|
||||||
|
createLayoutDescriptor("keyboard_layout_english_without_script_code")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// If script code not explicitly provided for Japanese should rely on Uscript to find
|
||||||
|
// derived script code and hence no suitable layout will be found.
|
||||||
|
keyboardLayouts =
|
||||||
|
keyboardLayoutManager.getKeyboardLayoutListForInputDevice(
|
||||||
|
keyboardDevice.identifier, USER_ID, imeInfo,
|
||||||
|
createImeSubtypeForLanguageTag("ja-JP")
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
"New UI: getKeyboardLayoutListForInputDevice API should return empty list of " +
|
||||||
|
"supported layouts with matching script code for ja-JP",
|
||||||
|
0,
|
||||||
|
keyboardLayouts.size
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,10 +810,10 @@ class KeyboardLayoutManagerTests {
|
|||||||
private fun createLayoutDescriptor(keyboardName: String): String =
|
private fun createLayoutDescriptor(keyboardName: String): String =
|
||||||
"$PACKAGE_NAME/$RECEIVER_NAME/$keyboardName"
|
"$PACKAGE_NAME/$RECEIVER_NAME/$keyboardName"
|
||||||
|
|
||||||
private fun areScriptsCompatible(scriptList1: IntArray, scriptList2: IntArray): Boolean {
|
private fun containsLayout(layoutList: Array<KeyboardLayout>, layoutDesc: String): Boolean {
|
||||||
for (s1 in scriptList1) {
|
for (kl in layoutList) {
|
||||||
for (s2 in scriptList2) {
|
if (kl.descriptor.equals(layoutDesc)) {
|
||||||
if (s1 == s2) return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
Reference in New Issue
Block a user