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

Commit 4c75ea85 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Check all regexp patterns in ResourceUtils.getDeviceOverrideValue

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

Change-Id: I42a4780bbfd2b083f4e27e61ec513aa875907344
parent a2d8d30f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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>
+58 −23
Original line number Diff line number Diff line
@@ -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);
+47 −37
Original line number Diff line number Diff line
@@ -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));
    }
}