diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 475e92f2e0767542f167479be70062d4fa5b3e22..4c7ed6956e925e94baabe5d17e90ca68e5ce6535 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -431,6 +431,7 @@
             <!--  This should be aligned with KeyboardId.IME_ACTION_* -->
             <enum name="actionCustomLabel" value="0x100" />
         </attr>
+        <attr name="isIconDefined" format="string" />
         <attr name="localeCode" format="string" />
         <attr name="languageCode" format="string" />
         <attr name="countryCode" format="string" />
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index dfe0df04c2847e071e83316535853b086d65522e..2aeeed87f7dc905c40db06a03489fb00280e7840 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -664,6 +664,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
                     R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine());
             final boolean imeActionMatched = matchInteger(caseAttr,
                     R.styleable.Keyboard_Case_imeAction, id.imeAction());
+            final boolean isIconDefinedMatched = isIconDefined(caseAttr,
+                    R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
             final boolean localeCodeMatched = matchString(caseAttr,
                     R.styleable.Keyboard_Case_localeCode, id.mLocale.toString());
             final boolean languageCodeMatched = matchString(caseAttr,
@@ -675,10 +677,11 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
                     && passwordInputMatched && clobberSettingsKeyMatched
                     && supportsSwitchingToShortcutImeMatched && hasShortcutKeyMatched
                     && languageSwitchKeyEnabledMatched && isMultiLineMatched && imeActionMatched
-                    && localeCodeMatched && languageCodeMatched && countryCodeMatched;
+                    && isIconDefinedMatched && localeCodeMatched && languageCodeMatched
+                    && countryCodeMatched;
 
             if (DEBUG) {
-                startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
+                startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
                         textAttr(caseAttr.getString(
                                 R.styleable.Keyboard_Case_keyboardLayoutSet), "keyboardLayoutSet"),
                         textAttr(caseAttr.getString(
@@ -704,6 +707,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
                                 "languageSwitchKeyEnabled"),
                         booleanAttr(caseAttr, R.styleable.Keyboard_Case_isMultiLine,
                                 "isMultiLine"),
+                        textAttr(caseAttr.getString(R.styleable.Keyboard_Case_isIconDefined),
+                                "isIconDefined"),
                         textAttr(caseAttr.getString(R.styleable.Keyboard_Case_localeCode),
                                 "localeCode"),
                         textAttr(caseAttr.getString(R.styleable.Keyboard_Case_languageCode),
@@ -755,6 +760,16 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
         return false;
     }
 
+    private static boolean isIconDefined(final TypedArray a, final int index,
+            final KeyboardIconsSet iconsSet) {
+        if (!a.hasValue(index)) {
+            return true;
+        }
+        final String iconName = a.getString(index);
+        final int iconId = KeyboardIconsSet.getIconId(iconName);
+        return iconsSet.getIconDrawable(iconId) != null;
+    }
+
     private boolean parseDefault(final XmlPullParser parser, final KeyboardRow row,
             final boolean skip) throws XmlPullParserException, IOException {
         if (DEBUG) startTag("<%s>", TAG_DEFAULT);