Check all regexp patterns in ResourceUtils.getDeviceOverrideValue

This change also fixes a regexp error of Galaxy S III.

Change-Id: I42a4780bbfd2b083f4e27e61ec513aa875907344
main
Tadashi G. Takaoka 2013-05-23 14:43:12 -07:00
parent a2d8d30f8e
commit 4c75ea858a
3 changed files with 107 additions and 62 deletions

View File

@ -37,7 +37,7 @@
<item>MODEL=(SAMSUNG-)?GT-I(930[05][NT]?|9308):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?SGH-(T999[V]?|I747[M]?|N064|N035):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?SCH-(J021|R530|I535|I939):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?(SCL21|SC-06D|SC-03E]):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?(SCL21|SC-06D|SC-03E):MANUFACTURER=samsung,8</item>
<item>MODEL=(SAMSUNG-)?(SHV-210[KLS]?|SPH-L710):MANUFACTURER=samsung,8</item>
<!-- LG Optimus G -->
<item>MODEL=LG-E97[013]|LS970|L-01E:MANUFACTURER=LGE,15</item>

View File

@ -27,6 +27,7 @@ import com.android.inputmethod.annotations.UsedForTesting;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.PatternSyntaxException;
public final class ResourceUtils {
private static final String TAG = ResourceUtils.class.getSimpleName();
@ -83,7 +84,9 @@ public final class ResourceUtils {
return overrideValue;
}
final String defaultValue = findDefaultConstant(overrideArray);
String defaultValue = null;
try {
defaultValue = findDefaultConstant(overrideArray);
// The defaultValue might be an empty string.
if (defaultValue == null) {
Log.w(TAG, "Couldn't find override value nor default value:"
@ -95,10 +98,25 @@ public final class ResourceUtils {
+ " build=" + sBuildKeyValuesDebugString
+ " default=" + defaultValue);
}
} catch (final DeviceOverridePatternSyntaxError e) {
Log.w(TAG, "Syntax error, ignored", e);
}
sDeviceOverrideValueMap.put(key, defaultValue);
return defaultValue;
}
@SuppressWarnings("serial")
static class DeviceOverridePatternSyntaxError extends Exception {
public DeviceOverridePatternSyntaxError(final String message, final String expression) {
this(message, expression, null);
}
public DeviceOverridePatternSyntaxError(final String message, final String expression,
final Throwable throwable) {
super(message + ": " + expression, throwable);
}
}
/**
* Find the condition that fulfills specified key value pairs from an array of
* "condition,constant", and return the corresponding string constant. A condition is
@ -123,10 +141,12 @@ public final class ResourceUtils {
if (conditionConstantArray == null || keyValuePairs == null) {
return null;
}
String foundValue = null;
for (final String conditionConstant : conditionConstantArray) {
final int posComma = conditionConstant.indexOf(',');
if (posComma < 0) {
throw new RuntimeException("Array element has no comma: " + conditionConstant);
Log.w(TAG, "Array element has no comma: " + conditionConstant);
continue;
}
final String condition = conditionConstant.substring(0, posComma);
if (condition.isEmpty()) {
@ -134,44 +154,59 @@ public final class ResourceUtils {
// {@link #findConstantForDefault(String[])}.
continue;
}
try {
if (fulfillsCondition(keyValuePairs, condition)) {
return conditionConstant.substring(posComma + 1);
// Take first match
if (foundValue == null) {
foundValue = conditionConstant.substring(posComma + 1);
}
// And continue walking through all conditions.
}
} catch (final DeviceOverridePatternSyntaxError e) {
Log.w(TAG, "Syntax error, ignored", e);
}
}
return null;
return foundValue;
}
private static boolean fulfillsCondition(final HashMap<String,String> keyValuePairs,
final String condition) {
final String condition) throws DeviceOverridePatternSyntaxError {
final String[] patterns = condition.split(":");
// Check all patterns in a condition are true
boolean matchedAll = true;
for (final String pattern : patterns) {
final int posEqual = pattern.indexOf('=');
if (posEqual < 0) {
throw new RuntimeException("Pattern has no '=': " + condition);
throw new DeviceOverridePatternSyntaxError("Pattern has no '='", condition);
}
final String key = pattern.substring(0, posEqual);
final String value = keyValuePairs.get(key);
if (value == null) {
throw new RuntimeException("Found unknown key: " + condition);
throw new DeviceOverridePatternSyntaxError("Unknown key", condition);
}
final String patternRegexpValue = pattern.substring(posEqual + 1);
try {
if (!value.matches(patternRegexpValue)) {
return false;
matchedAll = false;
// And continue walking through all patterns.
}
} catch (final PatternSyntaxException e) {
throw new DeviceOverridePatternSyntaxError("Syntax error", condition, e);
}
}
return true;
return matchedAll;
}
@UsedForTesting
static String findDefaultConstant(final String[] conditionConstantArray) {
static String findDefaultConstant(final String[] conditionConstantArray)
throws DeviceOverridePatternSyntaxError {
if (conditionConstantArray == null) {
return null;
}
for (final String condition : conditionConstantArray) {
final int posComma = condition.indexOf(',');
if (posComma < 0) {
throw new RuntimeException("Array element has no comma: " + condition);
throw new DeviceOverridePatternSyntaxError("Array element has no comma", condition);
}
if (posComma == 0) { // condition is empty.
return condition.substring(posComma + 1);

View File

@ -19,17 +19,15 @@ package com.android.inputmethod.latin;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.inputmethod.latin.ResourceUtils.DeviceOverridePatternSyntaxError;
import java.util.HashMap;
@SmallTest
public class ResourceUtilsTests extends AndroidTestCase {
public void testFindDefaultConstant() {
final String[] nullArray = null;
assertNull(ResourceUtils.findDefaultConstant(nullArray));
final String[] emptyArray = {};
assertNull(ResourceUtils.findDefaultConstant(emptyArray));
final String[] array = {
"HARDWARE=grouper,0.3",
"HARDWARE=mako,0.4",
@ -37,7 +35,25 @@ public class ResourceUtilsTests extends AndroidTestCase {
"HARDWARE=manta,0.2",
",defaultValue2",
};
try {
assertNull(ResourceUtils.findDefaultConstant(nullArray));
assertNull(ResourceUtils.findDefaultConstant(emptyArray));
assertEquals(ResourceUtils.findDefaultConstant(array), "defaultValue1");
} catch (final DeviceOverridePatternSyntaxError e) {
fail(e.getMessage());
}
final String[] errorArray = {
"HARDWARE=grouper,0.3",
"no_comma"
};
try {
final String defaultValue = ResourceUtils.findDefaultConstant(errorArray);
fail("exception should be thrown: defaultValue=" + defaultValue);
} catch (final DeviceOverridePatternSyntaxError e) {
assertEquals("Array element has no comma: no_comma", e.getMessage());
}
}
public void testFindConstantForKeyValuePairsSimple() {
@ -67,33 +83,23 @@ public class ResourceUtilsTests extends AndroidTestCase {
final HashMap<String,String> keyValues = CollectionUtils.newHashMap();
keyValues.put(HARDWARE_KEY, "grouper");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3");
assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.put(HARDWARE_KEY, "mako");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4");
assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.put(HARDWARE_KEY, "manta");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2");
assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
try {
keyValues.clear();
keyValues.put("hardware", "grouper");
final String constant = ResourceUtils.findConstantForKeyValuePairs(keyValues, array);
fail("condition without HARDWARE must fail: constant=" + constant);
} catch (final RuntimeException e) {
assertEquals(e.getMessage(), "Found unknown key: HARDWARE=grouper");
}
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.clear();
keyValues.put(HARDWARE_KEY, "MAKO");
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.put(HARDWARE_KEY, "mantaray");
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
try {
final String constant = ResourceUtils.findConstantForKeyValuePairs(
emptyKeyValue, array);
fail("emptyCondition shouldn't match: constant=" + constant);
} catch (final RuntimeException e) {
assertEquals(e.getMessage(), "Found unknown key: HARDWARE=grouper");
}
assertNull(ResourceUtils.findConstantForKeyValuePairs(emptyKeyValue, array));
}
public void testFindConstantForKeyValuePairsCombined() {
@ -102,6 +108,8 @@ public class ResourceUtilsTests extends AndroidTestCase {
final String MANUFACTURER_KEY = "MANUFACTURER";
final String[] array = {
",defaultValue",
"no_comma",
"error_pattern,0.1",
"HARDWARE=grouper:MANUFACTURER=asus,0.3",
"HARDWARE=mako:MODEL=Nexus 4,0.4",
"HARDWARE=manta:MODEL=Nexus 10:MANUFACTURER=samsung,0.2"
@ -117,25 +125,25 @@ public class ResourceUtilsTests extends AndroidTestCase {
keyValues.put(HARDWARE_KEY, "grouper");
keyValues.put(MODEL_KEY, "Nexus 7");
keyValues.put(MANUFACTURER_KEY, "asus");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3");
assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray));
keyValues.clear();
keyValues.put(HARDWARE_KEY, "mako");
keyValues.put(MODEL_KEY, "Nexus 4");
keyValues.put(MANUFACTURER_KEY, "LGE");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4");
assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray));
keyValues.clear();
keyValues.put(HARDWARE_KEY, "manta");
keyValues.put(MODEL_KEY, "Nexus 10");
keyValues.put(MANUFACTURER_KEY, "samsung");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2");
assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray));
keyValues.put(HARDWARE_KEY, "mantaray");
assertNull(ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray), "0.2");
assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, failArray));
}
public void testFindConstantForKeyValuePairsRegexp() {
@ -144,6 +152,8 @@ public class ResourceUtilsTests extends AndroidTestCase {
final String MANUFACTURER_KEY = "MANUFACTURER";
final String[] array = {
",defaultValue",
"no_comma",
"HARDWARE=error_regexp:MANUFACTURER=error[regexp,0.1",
"HARDWARE=grouper|tilapia:MANUFACTURER=asus,0.3",
"HARDWARE=[mM][aA][kK][oO]:MODEL=Nexus 4,0.4",
"HARDWARE=manta.*:MODEL=Nexus 10:MANUFACTURER=samsung,0.2"
@ -153,24 +163,24 @@ public class ResourceUtilsTests extends AndroidTestCase {
keyValues.put(HARDWARE_KEY, "grouper");
keyValues.put(MODEL_KEY, "Nexus 7");
keyValues.put(MANUFACTURER_KEY, "asus");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3");
assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.put(HARDWARE_KEY, "tilapia");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.3");
assertEquals("0.3", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.clear();
keyValues.put(HARDWARE_KEY, "mako");
keyValues.put(MODEL_KEY, "Nexus 4");
keyValues.put(MANUFACTURER_KEY, "LGE");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4");
assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.put(HARDWARE_KEY, "MAKO");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.4");
assertEquals("0.4", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.clear();
keyValues.put(HARDWARE_KEY, "manta");
keyValues.put(MODEL_KEY, "Nexus 10");
keyValues.put(MANUFACTURER_KEY, "samsung");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2");
assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
keyValues.put(HARDWARE_KEY, "mantaray");
assertEquals(ResourceUtils.findConstantForKeyValuePairs(keyValues, array), "0.2");
assertEquals("0.2", ResourceUtils.findConstantForKeyValuePairs(keyValues, array));
}
}