diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index c37c5827420150665aa3b8c764cbe0cf7a91b26e..9892d7835a0ff1cded73218fb0da20631b786ab7 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -191,8 +191,8 @@
         <attr name="iconShortcutKey" format="reference" />
         <attr name="iconShortcutForLabel" format="reference" />
         <attr name="iconSpaceKeyForNumberLayout" format="reference" />
-        <attr name="iconShortcutKeyDisabled" format="reference" />
         <attr name="iconShiftKeyShifted" format="reference" />
+        <attr name="iconDisabledShortcutKey" format="reference" />
         <attr name="iconPreviewTabKey" format="reference" />
     </declare-styleable>
 
@@ -245,23 +245,29 @@
         </attr>
         <!-- The icon to display on the key instead of the label. -->
         <attr name="keyIcon" format="enum">
-            <!-- This should be aligned with KeyboardIcons.ICON_* -->
+            <!-- This should be aligned with the KeyboardIcons.ICONS_TO_ATTRS_MAP -->
             <enum name="iconShiftKey" value="1" />
             <enum name="iconDeleteKey" value="2" />
+            <!-- This is also represented as "@icon/3" in keyboard layout XML. -->
             <enum name="iconSettingsKey" value="3" />
             <enum name="iconSpaceKey" value="4" />
             <enum name="iconReturnKey" value="5" />
             <enum name="iconSearchKey" value="6" />
+            <!-- This is also represented as "@icon/7" in keyboard layout XML. -->
             <enum name="iconTabKey" value="7" />
             <enum name="iconShortcutKey" value="8" />
             <enum name="iconShortcutForLabel" value="9" />
-            <enum name="iconShortcutKeyDisabled" value="10" />
-            <enum name="iconSpaceKeyForNumberLayout" value="11" />
-            <enum name="iconShiftKeyShifted" value="12" />
+            <enum name="iconSpaceKeyForNumberLayout" value="10" />
+            <enum name="iconShiftKeyShifted" value="11" />
+        </attr>
+        <!-- The icon for disabled key -->
+        <attr name="keyIconDisabled" format="enum">
+            <!-- This should be aligned with the KeyboardIcons.ICONS_TO_ATTRS_MAP -->
+            <enum name="iconDisabledShortcutKey" value="12" />
         </attr>
         <!-- The icon to show in the popup preview. -->
         <attr name="keyIconPreview" format="enum">
-            <!-- This should be aligned with KeyboardIcons.ICON_PREVIEW_* -->
+            <!-- This should be aligned with the KeyboardIcons.ICONS_TO_ATTRS_MAP -->
             <enum name="iconPreviewTabKey" value="13" />
         </attr>
         <!-- The key style to specify a set of key attributes defined by <key_style/> -->
diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml
index 1caa16a559fa6c2cdf20f54f0a0b48d9bf0579b4..1c5a5f720a922d75a5e8d5f7fe61afcc0bf199c8 100644
--- a/java/res/values/keyboard-icons-black.xml
+++ b/java/res/values/keyboard-icons-black.xml
@@ -30,9 +30,9 @@
         <item name="iconTabKey">@drawable/sym_bkeyboard_tab</item>
         <item name="iconShortcutKey">@drawable/sym_bkeyboard_mic</item>
         <item name="iconShortcutForLabel">@drawable/sym_bkeyboard_label_mic</item>
-        <item name="iconShortcutKeyDisabled">@drawable/sym_bkeyboard_voice_off</item>
         <item name="iconSpaceKeyForNumberLayout">@drawable/sym_bkeyboard_space</item>
         <item name="iconShiftKeyShifted">@drawable/sym_bkeyboard_shift_locked</item>
+        <item name="iconDisabledShortcutKey">@drawable/sym_bkeyboard_voice_off</item>
         <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
     </style>
 </resources>
diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml
index 0d4a3c7580581cc80f3e20ee6a8c56bb395862c5..f68be5f1e8498004a19919b04d1e8c5cc3f06889 100644
--- a/java/res/values/keyboard-icons-ics.xml
+++ b/java/res/values/keyboard-icons-ics.xml
@@ -29,9 +29,9 @@
         <item name="iconTabKey">@drawable/sym_keyboard_tab_holo</item>
         <item name="iconShortcutKey">@drawable/sym_keyboard_voice_holo</item>
         <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic_holo</item>
-        <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo</item>
         <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space_holo</item>
         <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo</item>
+        <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item>
         <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
     </style>
 </resources>
diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml
index a3bb268a0b9e427a21739ad5c8368371433eda98..35197a1c01f2820cddf6247688bd4e10c442f813 100644
--- a/java/res/values/keyboard-icons-white.xml
+++ b/java/res/values/keyboard-icons-white.xml
@@ -26,10 +26,10 @@
         <item name="iconTabKey">@drawable/sym_keyboard_tab</item>
         <item name="iconShortcutKey">@drawable/sym_keyboard_mic</item>
         <item name="iconShortcutForLabel">@drawable/sym_keyboard_label_mic</item>
-        <!-- TODO: Needs non-holo disabled shortcut icon drawable -->
-        <item name="iconShortcutKeyDisabled">@drawable/sym_keyboard_voice_off_holo</item>
         <item name="iconSpaceKeyForNumberLayout">@drawable/sym_keyboard_space</item>
         <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked</item>
+        <!-- TODO: Needs non-holo disabled shortcut icon drawable -->
+        <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item>
         <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item>
     </style>
 </resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index d4460c93dd0bdc365f2314583175e1b1e5b485f9..c4e39e35705a2c9197ec42a4c8afc3827a75d86e 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -307,7 +307,7 @@
         <item name="spacebarTextRatio">@fraction/spacebar_text_ratio</item>
         <item name="spacebarTextColor">#FFC0C0C0</item>
         <item name="spacebarTextShadowColor">#80000000</item>
-        </style>
+    </style>
     <style
         name="MiniKeyboard.IceCreamSandwich"
         parent="Keyboard.IceCreamSandwich"
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 27560109062298751bc6da3f31120ee8d84d306d..1dd0307c71bfb60993768ae50143f38ea79149aa 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -76,6 +76,7 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
+        latin:keyIconDisabled="iconDisabledShortcutKey"
         latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
         latin:altCode="@integer/key_dummy"
         latin:parentStyle="f2PopupStyle" />
diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml
index 83de4dd242e77b71a2193e85196dca176797f811..7292fe169cab93e5740f0e1dacc7fed5ab7228a5 100644
--- a/java/res/xml-sw768dp/kbd_key_styles.xml
+++ b/java/res/xml-sw768dp/kbd_key_styles.xml
@@ -58,6 +58,7 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
+        latin:keyIconDisabled="iconDisabledShortcutKey"
         latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
         latin:altCode="@integer/key_dummy"
         latin:backgroundType="functional" />
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
index 6fdb3f5e801ccbc2ac5db45a4fbbc96c59128ae4..7869d21d0a969f474a974445d05cd52aca40ac4e 100644
--- a/java/res/xml/kbd_key_styles.xml
+++ b/java/res/xml/kbd_key_styles.xml
@@ -162,6 +162,7 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
+        latin:keyIconDisabled="iconDisabledShortcutKey"
         latin:keyActionFlags="noKeyPreview|altCodeWhileTyping"
         latin:altCode="@integer/key_space"
         latin:parentStyle="f1PopupStyle" />
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index b7d8c4a3e54517756d811c8d5744339f75ee491a..e1e74fc9a27c16b617fe12bdcc0f6eca3ffe399c 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -72,9 +72,11 @@ public class Key {
     private static final int LABEL_FLAGS_WITH_ICON_RIGHT = 0x2000;
     private static final int LABEL_FLAGS_AUTO_X_SCALE = 0x4000;
 
-    // TODO: This should be public final
+    // TODO: These icon references could be int (icon attribute id)
     /** Icon to display instead of a label. Icon takes precedence over a label */
     private Drawable mIcon;
+    /** Icon for disabled state */
+    private Drawable mDisabledIcon;
     /** Preview version of the icon, for the preview popup */
     public final Drawable mPreviewIcon;
 
@@ -164,7 +166,7 @@ public class Key {
     }
 
     private static Drawable getIcon(Keyboard.Params params, String moreKeySpec) {
-        return params.mIconsSet.getIcon(MoreKeySpecParser.getIconId(moreKeySpec));
+        return params.mIconsSet.getIconByIconId(MoreKeySpecParser.getIconId(moreKeySpec));
     }
 
     /**
@@ -198,6 +200,7 @@ public class Key {
         mCode = code;
         mAltCode = Keyboard.CODE_DUMMY;
         mIcon = icon;
+        mDisabledIcon = null;
         mPreviewIcon = null;
         // Horizontal gap is divided equally to both sides of the key.
         mX = x + mHorizontalGap / 2;
@@ -274,10 +277,12 @@ public class Key {
                 R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0);
         mVisualInsetsRight = (int) Keyboard.Builder.getDimensionOrFraction(keyAttr,
                 R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0);
-        mPreviewIcon = iconsSet.getIcon(style.getInt(keyAttr,
+        mPreviewIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
                 R.styleable.Keyboard_Key_keyIconPreview, KeyboardIconsSet.ICON_UNDEFINED));
-        mIcon = iconsSet.getIcon(style.getInt(keyAttr, R.styleable.Keyboard_Key_keyIcon,
-                KeyboardIconsSet.ICON_UNDEFINED));
+        mIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+                R.styleable.Keyboard_Key_keyIcon, KeyboardIconsSet.ICON_UNDEFINED));
+        mDisabledIcon = iconsSet.getIconByIconId(style.getInt(keyAttr,
+                R.styleable.Keyboard_Key_keyIconDisabled, KeyboardIconsSet.ICON_UNDEFINED));
         mHintLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
 
         mLabel = style.getText(keyAttr, R.styleable.Keyboard_Key_keyLabel);
@@ -459,7 +464,7 @@ public class Key {
     }
 
     public Drawable getIcon() {
-        return mIcon;
+        return mEnabled ? mIcon : mDisabledIcon;
     }
 
     // TODO: Get rid of this method.
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 444360d9a599c882d1d828aa4157a8d895d3b252..9f4b8811d16a3879c14028bea56d474b4cab38a9 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -192,9 +192,10 @@ public class Keyboard {
             // To represent "shift locked" state. The highlight is handled by background image that
             // might be a StateListDrawable.
             key.setHighlightOn(newShiftLockState);
-            final int iconId = newShiftLockState ? KeyboardIconsSet.ICON_SHIFT_KEY_SHIFTED
-                    : KeyboardIconsSet.ICON_SHIFT_KEY;
-            key.setIcon(mIconsSet.getIcon(iconId));
+            final int attrId = newShiftLockState
+                    ? R.styleable.Keyboard_iconShiftKeyShifted
+                    : R.styleable.Keyboard_iconShiftKey;
+            key.setIcon(mIconsSet.getIconByAttrId(attrId));
         }
         mShiftState.setShiftLocked(newShiftLockState);
     }
@@ -208,9 +209,10 @@ public class Keyboard {
     void setShifted(boolean newShiftState) {
         if (!mShiftState.isShiftLocked()) {
             for (final Key key : mShiftKeys) {
-                final int iconId = newShiftState ? KeyboardIconsSet.ICON_SHIFT_KEY_SHIFTED
-                        : KeyboardIconsSet.ICON_SHIFT_KEY;
-                key.setIcon(mIconsSet.getIcon(iconId));
+                final int attrId = newShiftState
+                        ? R.styleable.Keyboard_iconShiftKeyShifted
+                        : R.styleable.Keyboard_iconShiftKey;
+                key.setIcon(mIconsSet.getIconByAttrId(attrId));
             }
         }
         mShiftState.setShifted(newShiftState);
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index aefa50b221cbc1cec1fa2df043bb3547e4167b9e..3433cd4558e3cc3f8c907866153edf575a257338 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -47,7 +47,6 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
 import com.android.inputmethod.deprecated.VoiceProxy;
 import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
 import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.latin.LatinIME;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
@@ -357,7 +356,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         mMoreKeysPanelCache.clear();
 
         mSpaceKey = keyboard.getKey(Keyboard.CODE_SPACE);
-        mSpaceIcon = keyboard.mIconsSet.getIcon(KeyboardIconsSet.ICON_SPACE_KEY);
+        mSpaceIcon = keyboard.mIconsSet.getIconByAttrId(R.styleable.Keyboard_iconSpaceKey);
         final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
         mSpacebarTextSize = keyHeight * mSpacebarTextRatio;
         mSpacebarLocale = keyboard.mId.mLocale;
@@ -750,9 +749,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         final Key shortcutKey = keyboard.getKey(Keyboard.CODE_SHORTCUT);
         if (shortcutKey == null) return;
         shortcutKey.setEnabled(available);
-        final int iconId = available ? KeyboardIconsSet.ICON_SHORTCUT_KEY
-                : KeyboardIconsSet.ICON_SHORTCUT_KEY_DISABLED;
-        shortcutKey.setIcon(keyboard.mIconsSet.getIcon(iconId));
         invalidateKey(shortcutKey);
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 9b99dc42f2f7ae4466feace0e01f2c51d655dbfe..5dd8340fc11452cd3aa958ddb788a396c0876be4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -161,6 +161,7 @@ public class KeyStyles {
             readTextArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
             readFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
             readInt(keyAttr, R.styleable.Keyboard_Key_keyIcon);
+            readInt(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
             readInt(keyAttr, R.styleable.Keyboard_Key_keyIconPreview);
             readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
             readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index c8a75a92a660bce137c5705094d0e08fc12a622c..6313a61b5f7185f9a43c2a1e726f515030cca52c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -23,88 +23,75 @@ import android.util.Log;
 
 import com.android.inputmethod.latin.R;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
 public class KeyboardIconsSet {
     private static final String TAG = KeyboardIconsSet.class.getSimpleName();
 
     public static final int ICON_UNDEFINED = 0;
 
-    // TODO: Make all enums private
-    // This should be aligned with Keyboard.keyIcon enum.
-    public static final int ICON_SHIFT_KEY = 1;
-    private static final int ICON_DELETE_KEY = 2;
-    // This is also represented as "@icon/3" in keyboard layout XML.
-    private static final int ICON_SETTINGS_KEY = 3;
-    public static final int ICON_SPACE_KEY = 4;
-    private static final int ICON_RETURN_KEY = 5;
-    private static final int ICON_SEARCH_KEY = 6;
-    // This is also represented as "@icon/7" in keyboard layout XML.
-    private static final int ICON_TAB_KEY = 7;
-    public static final int ICON_SHORTCUT_KEY = 8;
-    private static final int ICON_SHORTCUT_FOR_LABEL = 9;
-    public static final int ICON_SHORTCUT_KEY_DISABLED = 10;
-    private static final int ICON_SPACE_KEY_FOR_NUMBER_LAYOUT = 11;
-    public static final int ICON_SHIFT_KEY_SHIFTED = 12;
-    // This should be aligned with Keyboard.keyIconPreview enum.
-    private static final int ICON_PREVIEW_TAB_KEY = 13;
+    private final Map<Integer, Drawable> mIcons = new HashMap<Integer, Drawable>();
 
-    private static final int ICON_LAST = 13;
+    // The key value should be aligned with the enum value of Keyboard.icon*.
+    private static final Map<Integer, Integer> ICONS_TO_ATTRS_MAP = new HashMap<Integer, Integer>();
+    private static final Collection<Integer> VALID_ATTRS;
 
-    private final Drawable mIcons[] = new Drawable[ICON_LAST + 1];
+    static {
+        addIconIdMap(1, R.styleable.Keyboard_iconShiftKey);
+        addIconIdMap(2, R.styleable.Keyboard_iconDeleteKey);
+        // This is also represented as "@icon/3" in keyboard layout XML.
+        addIconIdMap(3, R.styleable.Keyboard_iconSettingsKey);
+        addIconIdMap(4, R.styleable.Keyboard_iconSpaceKey);
+        addIconIdMap(5, R.styleable.Keyboard_iconReturnKey);
+        addIconIdMap(6, R.styleable.Keyboard_iconSearchKey);
+        // This is also represented as "@icon/7" in keyboard layout XML.
+        addIconIdMap(7, R.styleable.Keyboard_iconTabKey);
+        addIconIdMap(8, R.styleable.Keyboard_iconShortcutKey);
+        addIconIdMap(9, R.styleable.Keyboard_iconShortcutForLabel);
+        addIconIdMap(10, R.styleable.Keyboard_iconSpaceKeyForNumberLayout);
+        addIconIdMap(11, R.styleable.Keyboard_iconShiftKeyShifted);
+        addIconIdMap(12, R.styleable.Keyboard_iconDisabledShortcutKey);
+        addIconIdMap(13, R.styleable.Keyboard_iconPreviewTabKey);
+        VALID_ATTRS = ICONS_TO_ATTRS_MAP.values();
+    }
 
-    private static final int getIconId(final int attrIndex) {
-        switch (attrIndex) {
-        case R.styleable.Keyboard_iconShiftKey:
-            return ICON_SHIFT_KEY;
-        case R.styleable.Keyboard_iconDeleteKey:
-            return ICON_DELETE_KEY;
-        case R.styleable.Keyboard_iconSettingsKey:
-            return ICON_SETTINGS_KEY;
-        case R.styleable.Keyboard_iconSpaceKey:
-            return ICON_SPACE_KEY;
-        case R.styleable.Keyboard_iconReturnKey:
-            return ICON_RETURN_KEY;
-        case R.styleable.Keyboard_iconSearchKey:
-            return ICON_SEARCH_KEY;
-        case R.styleable.Keyboard_iconTabKey:
-            return ICON_TAB_KEY;
-        case R.styleable.Keyboard_iconShortcutKey:
-            return ICON_SHORTCUT_KEY;
-        case R.styleable.Keyboard_iconShortcutForLabel:
-            return ICON_SHORTCUT_FOR_LABEL;
-        case R.styleable.Keyboard_iconShortcutKeyDisabled:
-            return ICON_SHORTCUT_KEY_DISABLED;
-        case R.styleable.Keyboard_iconSpaceKeyForNumberLayout:
-            return ICON_SPACE_KEY_FOR_NUMBER_LAYOUT;
-        case R.styleable.Keyboard_iconShiftKeyShifted:
-            return ICON_SHIFT_KEY_SHIFTED;
-        case R.styleable.Keyboard_iconPreviewTabKey:
-            return ICON_PREVIEW_TAB_KEY;
-        default:
-            return ICON_UNDEFINED;
-        }
+    private static void addIconIdMap(int iconId, int attrId) {
+        ICONS_TO_ATTRS_MAP.put(iconId, attrId);
     }
 
     public void loadIcons(final TypedArray keyboardAttrs) {
-        final int count = keyboardAttrs.getIndexCount();
-        for (int i = 0; i < count; i++) {
-            final int attrIndex = keyboardAttrs.getIndex(i);
-            final int iconId = getIconId(attrIndex);
-            if (iconId != ICON_UNDEFINED) {
-                try {
-                    mIcons[iconId] = setDefaultBounds(keyboardAttrs.getDrawable(attrIndex));
-                } catch (Resources.NotFoundException e) {
-                    Log.w(TAG, "Drawable resource for icon #" + iconId + " not found");
-                }
+        for (final Integer attrId : VALID_ATTRS) {
+            try {
+                final Drawable icon = keyboardAttrs.getDrawable(attrId);
+                if (icon == null) continue;
+                setDefaultBounds(icon);
+                mIcons.put(attrId, icon);
+            } catch (Resources.NotFoundException e) {
+                Log.w(TAG, "Drawable resource for icon #"
+                        + keyboardAttrs.getResources().getResourceEntryName(attrId)
+                        + " not found");
             }
         }
     }
 
-    public Drawable getIcon(final int iconId) {
-        if (iconId == ICON_UNDEFINED)
+    public Drawable getIconByIconId(final Integer iconId) {
+        if (iconId == ICON_UNDEFINED) {
             return null;
-        if (iconId < 0 || iconId >= mIcons.length)
+        }
+        final Integer attrId = ICONS_TO_ATTRS_MAP.get(iconId);
+        if (attrId == null) {
             throw new IllegalArgumentException("icon id is out of range: " + iconId);
-        return mIcons[iconId];
+        }
+        return getIconByAttrId(attrId);
+    }
+
+    public Drawable getIconByAttrId(final Integer attrId) {
+        if (!VALID_ATTRS.contains(attrId)) {
+            throw new IllegalArgumentException("unknown icon attribute id: " + attrId);
+        }
+        return mIcons.get(attrId);
     }
 
     private static Drawable setDefaultBounds(final Drawable icon)  {