Merge "Enrich the Spanish dictionary."
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 27896fd..2762a9f 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -67,7 +67,6 @@
 
         // These only need to be initialized if the kill switch is off.
         sInstance.initInternal(context);
-        KeyCodeDescriptionMapper.init();
     }
 
     public static AccessibilityUtils getInstance() {
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
index 27c4732..3a64531 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
@@ -31,7 +31,7 @@
 
 import java.util.Locale;
 
-public final class KeyCodeDescriptionMapper {
+final class KeyCodeDescriptionMapper {
     private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName();
     private static final String SPOKEN_LETTER_RESOURCE_NAME_FORMAT = "spoken_accented_letter_%04X";
     private static final String SPOKEN_SYMBOL_RESOURCE_NAME_FORMAT = "spoken_symbol_%04X";
@@ -40,24 +40,16 @@
     // The resource ID of the string spoken for obscured keys
     private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot;
 
-    private static KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper();
-
-    // Sparse array of spoken description resource IDs indexed by key codes
-    private final SparseIntArray mKeyCodeMap;
-
-    public static void init() {
-        sInstance.initInternal();
-    }
+    private static final KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper();
 
     public static KeyCodeDescriptionMapper getInstance() {
         return sInstance;
     }
 
-    private KeyCodeDescriptionMapper() {
-        mKeyCodeMap = new SparseIntArray();
-    }
+    // Sparse array of spoken description resource IDs indexed by key codes
+    private final SparseIntArray mKeyCodeMap = new SparseIntArray();
 
-    private void initInternal() {
+    private KeyCodeDescriptionMapper() {
         // Special non-character codes defined in Keyboard
         mKeyCodeMap.put(Constants.CODE_SPACE, R.string.spoken_description_space);
         mKeyCodeMap.put(Constants.CODE_DELETE, R.string.spoken_description_delete);
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
index 398a933..bbc18f0 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityDelegate.java
@@ -248,19 +248,15 @@
      * Synthesize a touch event from a hover event.
      *
      * @param touchAction The action of the synthesizing touch event.
-     * @param event The base hover event from that the touch event is synthesized.
+     * @param hoverEvent The base hover event from that the touch event is synthesized.
      * @return The synthesized touch event of <code>touchAction</code> that has pointer information
      * of <code>event</code>.
      */
     protected static MotionEvent synthesizeTouchEvent(final int touchAction,
-            final MotionEvent event) {
-        final long downTime = event.getDownTime();
-        final long eventTime = event.getEventTime();
-        final int actionIndex = event.getActionIndex();
-        final float x = event.getX(actionIndex);
-        final float y = event.getY(actionIndex);
-        final int pointerId = event.getPointerId(actionIndex);
-        return MotionEvent.obtain(downTime, eventTime, touchAction, x, y, pointerId);
+            final MotionEvent hoverEvent) {
+        final MotionEvent touchEvent = MotionEvent.obtain(hoverEvent);
+        touchEvent.setAction(touchAction);
+        return touchEvent;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
index a6997e2..18673a3 100644
--- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
+++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java
@@ -47,7 +47,7 @@
  * virtual views, thus conveying their logical structure.
  * </p>
  */
-public final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderCompat {
+final class KeyboardAccessibilityNodeProvider extends AccessibilityNodeProviderCompat {
     private static final String TAG = KeyboardAccessibilityNodeProvider.class.getSimpleName();
     private static final int UNDEFINED = Integer.MIN_VALUE;
 
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index cf68c56..89a60cc 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -467,15 +467,24 @@
 
     @Override
     public String toString() {
-        final String label;
-        if (StringUtils.codePointCount(mLabel) == 1 && mLabel.codePointAt(0) == mCode) {
-            label = "";
-        } else {
-            label = "/" + mLabel;
+        return toShortString() + " " + getX() + "," + getY() + " " + getWidth() + "x" + getHeight();
+    }
+
+    public String toShortString() {
+        final int code = getCode();
+        if (code == Constants.CODE_OUTPUT_TEXT) {
+            return getOutputText();
         }
-        return String.format(Locale.ROOT, "%s%s %d,%d %dx%d %s/%s/%s",
-                Constants.printableCode(mCode), label, mX, mY, mWidth, mHeight, mHintLabel,
-                KeyboardIconsSet.getIconName(mIconId), backgroundName(mBackgroundType));
+        return Constants.printableCode(code);
+    }
+
+    public String toLongString() {
+        final int iconId = getIconId();
+        final String topVisual = (iconId == KeyboardIconsSet.ICON_UNDEFINED)
+                ? KeyboardIconsSet.PREFIX_ICON + KeyboardIconsSet.getIconName(iconId) : getLabel();
+        final String hintLabel = getHintLabel();
+        final String visual = (hintLabel == null) ? topVisual : topVisual + "^" + hintLabel;
+        return toString() + " " + visual + "/" + backgroundName(mBackgroundType);
     }
 
     private static String backgroundName(final int backgroundType) {
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index 495cfa9..7787714 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -381,14 +381,12 @@
         final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
         mLanguageOnSpacebarTextSize = keyHeight * mLanguageOnSpacebarTextRatio;
 
-        final MainKeyboardAccessibilityDelegate accessibilityDelegate;
         if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
-            accessibilityDelegate = new MainKeyboardAccessibilityDelegate(this, mKeyDetector);
-            accessibilityDelegate.setKeyboard(keyboard);
+            mAccessibilityDelegate = new MainKeyboardAccessibilityDelegate(this, mKeyDetector);
+            mAccessibilityDelegate.setKeyboard(keyboard);
         } else {
-            accessibilityDelegate = null;
+            mAccessibilityDelegate = null;
         }
-        mAccessibilityDelegate = accessibilityDelegate;
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 7bf2f6c..ff6fd86 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -676,10 +676,10 @@
 
     private void onDownEvent(final int x, final int y, final long eventTime,
             final KeyDetector keyDetector) {
+        setKeyDetectorInner(keyDetector);
         if (DEBUG_EVENT) {
             printTouchEvent("onDownEvent:", x, y, eventTime);
         }
-        setKeyDetectorInner(keyDetector);
         // Naive up-to-down noise filter.
         final long deltaT = eventTime - mUpTime;
         if (deltaT < sParams.mTouchNoiseThresholdTime) {
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 05d3476..35012a4 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -254,14 +254,16 @@
         case CODE_LANGUAGE_SWITCH: return "languageSwitch";
         case CODE_EMOJI: return "emoji";
         case CODE_SHIFT_ENTER: return "shiftEnter";
+        case CODE_ALPHA_FROM_EMOJI: return "alpha";
         case CODE_UNSPECIFIED: return "unspec";
         case CODE_TAB: return "tab";
         case CODE_ENTER: return "enter";
-        case CODE_ALPHA_FROM_EMOJI: return "alpha";
+        case CODE_SPACE: return "space";
         default:
-            if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
-            if (code < 0x100) return String.format("'%c'", code);
-            return String.format("'\\u%04x'", code);
+            if (code < CODE_SPACE) return String.format("\\u%02x", code);
+            if (code < 0x100) return String.format("%c", code);
+            if (code < 0x10000) return String.format("\\u04x", code);
+            return String.format("\\U%05x", code);
         }
     }