diff options
Diffstat (limited to 'java/src')
14 files changed, 705 insertions, 116 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index 0a2b010b6..fbb13c25f 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -26,6 +26,7 @@ import android.util.Log; import android.util.Xml; import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.keyboard.internal.KeySpecParser.MoreKeySpec; import com.android.inputmethod.keyboard.internal.KeyStyles; import com.android.inputmethod.keyboard.internal.KeyStyles.KeyStyle; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; @@ -104,7 +105,7 @@ public class Key { /** Text to output when pressed. This can be multiple characters, like ".com" */ public final CharSequence mOutputText; /** More keys */ - public final String[] mMoreKeys; + public final MoreKeySpec[] mMoreKeys; /** More keys column number and flags */ private final int mMoreKeysColumnAndFlags; private static final int MORE_KEYS_COLUMN_MASK = 0x000000ff; @@ -140,15 +141,12 @@ public class Key { private boolean mEnabled = true; /** - * This constructor is being used only for key in more keys keyboard. + * This constructor is being used only for keys in more keys keyboard. */ - public Key(Resources res, Keyboard.Params params, String moreKeySpec, - int x, int y, int width, int height, int labelFlags) { - this(params, KeySpecParser.getLabel(moreKeySpec), null, - KeySpecParser.getIconId(moreKeySpec), - KeySpecParser.getCode(res, moreKeySpec), - KeySpecParser.getOutputText(moreKeySpec), - x, y, width, height, labelFlags); + public Key(Keyboard.Params params, MoreKeySpec moreKeySpec, int x, int y, int width, int height, + int labelFlags) { + this(params, moreKeySpec.mLabel, null, moreKeySpec.mIconId, moreKeySpec.mCode, + moreKeySpec.mOutputText, x, y, width, height, labelFlags); } /** @@ -278,13 +276,15 @@ public class Key { moreKeys = KeySpecParser.insertAddtionalMoreKeys(moreKeys, additionalMoreKeys); if (moreKeys != null) { actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS; + mMoreKeys = new MoreKeySpec[moreKeys.length]; for (int i = 0; i < moreKeys.length; i++) { - moreKeys[i] = adjustCaseOfStringForKeyboardId( - moreKeys[i], preserveCase, params.mId); + mMoreKeys[i] = new MoreKeySpec(adjustCaseOfStringForKeyboardId( + moreKeys[i], preserveCase, params.mId), params.mCodesSet); } + } else { + mMoreKeys = null; } mActionFlags = actionFlags; - mMoreKeys = moreKeys; if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) { mLabel = params.mId.mCustomActionLabel; @@ -300,8 +300,9 @@ public class Key { } String outputText = adjustCaseOfStringForKeyboardId(style.getString( keyAttr, R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId); - final int code = style.getInt( - keyAttr, R.styleable.Keyboard_Key_code, Keyboard.CODE_UNSPECIFIED); + final int code = KeySpecParser.parseCode(style.getString( + keyAttr, R.styleable.Keyboard_Key_code), + params.mCodesSet, Keyboard.CODE_UNSPECIFIED); // Choose the first letter of the label as primary code if not specified. if (code == Keyboard.CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) && !TextUtils.isEmpty(mLabel)) { @@ -331,9 +332,10 @@ public class Key { mCode = adjustCaseOfCodeForKeyboardId(code, preserveCase, params.mId); } mOutputText = outputText; - mAltCode = adjustCaseOfCodeForKeyboardId(style.getInt(keyAttr, - R.styleable.Keyboard_Key_altCode, Keyboard.CODE_UNSPECIFIED), preserveCase, - params.mId); + mAltCode = adjustCaseOfCodeForKeyboardId(KeySpecParser.parseCode(style.getString( + keyAttr, R.styleable.Keyboard_Key_altCode), + params.mCodesSet, Keyboard.CODE_UNSPECIFIED), + preserveCase, params.mId); mHashCode = computeHashCode(this); keyAttr.recycle(); diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 950b5e99b..36a988bb6 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -28,6 +28,7 @@ import android.util.Xml; import android.view.InflateException; import com.android.inputmethod.keyboard.internal.KeyStyles; +import com.android.inputmethod.keyboard.internal.KeyboardCodesSet; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -238,6 +239,7 @@ public class Keyboard { public final ArrayList<Key> mShiftKeys = new ArrayList<Key>(); public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>(); public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); + public final KeyboardCodesSet mCodesSet = new KeyboardCodesSet(); public KeyboardLayoutSet.KeysCache mKeysCache; @@ -775,6 +777,7 @@ public class Keyboard { params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0); params.mIconsSet.loadIcons(keyboardAttr); + params.mCodesSet.setLanguage(params.mId.mLocale.getLanguage()); final int resourceId = keyboardAttr.getResourceId( R.styleable.Keyboard_touchPositionCorrectionData, 0); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 2689e6e13..5ebf92cf7 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -41,7 +41,6 @@ import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; -import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -555,9 +554,12 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke * method on the base class if the subclass doesn't wish to handle the call. */ protected boolean onLongPress(Key parentKey, PointerTracker tracker) { + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinKeyboardView_onLongPress(); + } final int primaryCode = parentKey.mCode; if (parentKey.hasEmbeddedMoreKey()) { - final int embeddedCode = KeySpecParser.getCode(getResources(), parentKey.mMoreKeys[0]); + final int embeddedCode = parentKey.mMoreKeys[0].mCode; tracker.onLongPressed(); invokeCodeInput(embeddedCode); invokeReleaseKey(primaryCode); @@ -695,17 +697,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - // TODO: remove redundant calculations of size and pressure by - // removing UsabilityStudyLog code once the ResearchLogger is mature enough - final float size = me.getSize(index); - final float pressure = me.getPressure(index); - if (action != MotionEvent.ACTION_MOVE) { - // Skip ACTION_MOVE events as they are logged below - ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, - size, pressure); - } - } + ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, index, id, + x, y); } if (mKeyTimerHandler.isInKeyRepeat()) { @@ -773,13 +766,8 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke + pointerSize + "," + pointerPressure); } if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.sIsLogging) { - // TODO: earlier comment about redundant calculations applies here too - final float pointerSize = me.getSize(i); - final float pointerPressure = me.getPressure(i); - ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, - px, py, pointerSize, pointerPressure); - } + ResearchLogger.latinKeyboardView_processMotionEvent(me, action, eventTime, + i, pointerId, px, py); } } } else { diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 72a5d0f05..f8682d8ca 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -19,7 +19,7 @@ package com.android.inputmethod.keyboard; import android.graphics.Paint; import android.graphics.drawable.Drawable; -import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.keyboard.internal.KeySpecParser.MoreKeySpec; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StringUtils; @@ -301,8 +301,8 @@ public class MoreKeysKeyboard extends Keyboard { ? view.mKeyDrawParams.mKeyLabelSize : view.mKeyDrawParams.mKeyLetterSize); int maxWidth = minKeyWidth; - for (String moreKeySpec : parentKey.mMoreKeys) { - final String label = KeySpecParser.getLabel(moreKeySpec); + for (final MoreKeySpec spec : parentKey.mMoreKeys) { + final String label = spec.mLabel; // If the label is single letter, minKeyWidth is enough to hold the label. if (label != null && StringUtils.codePointCount(label) > 1) { final int width = (int)view.getLabelWidth(label, paint) + padding; @@ -336,13 +336,13 @@ public class MoreKeysKeyboard extends Keyboard { // label's code point count. final int moreKeyFlags = mParentKey.hasLabelsInMoreKeys() ? 0 : Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO; - final String[] moreKeys = mParentKey.mMoreKeys; + final MoreKeySpec[] moreKeys = mParentKey.mMoreKeys; for (int n = 0; n < moreKeys.length; n++) { - final String moreKeySpec = moreKeys[n]; + final MoreKeySpec moreKeySpec = moreKeys[n]; final int row = n / params.mNumColumns; final int x = params.getX(n, row); final int y = params.getY(row); - final Key key = new Key(mResources, params, moreKeySpec, x, y, + final Key key = new Key(params, moreKeySpec, x, y, params.mDefaultKeyWidth, params.mDefaultRowHeight, moreKeyFlags); params.markAsEdgeKey(key, row); params.onAddKey(key); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index ec9081681..24ab54730 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -23,6 +23,8 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.ArrayList; @@ -235,6 +237,10 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " enabled=" + key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange(key, + ignoreModifierKey); + } if (ignoreModifierKey) { return false; } @@ -259,6 +265,10 @@ public class PointerTracker { + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + " enabled=" + key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnCodeInput(key, x, y, ignoreModifierKey, + altersCode, code); + } if (ignoreModifierKey) { return; } @@ -284,6 +294,10 @@ public class PointerTracker { + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + " enabled="+ key.isEnabled()); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnRelease(key, primaryCode, withSliding, + ignoreModifierKey); + } if (ignoreModifierKey) { return; } @@ -295,6 +309,9 @@ public class PointerTracker { private void callListenerOnCancelInput() { if (DEBUG_LISTENER) Log.d(TAG, "onCancelInput"); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_callListenerOnCancelInput(); + } mListener.onCancelInput(); } @@ -479,6 +496,9 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT + " distance=" + distanceSquared); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared); + } mKeyAlreadyProcessed = true; return; } @@ -583,6 +603,9 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, String.format("onMoveEvent: sudden move is translated to " + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y)); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.pointerTracker_onMoveEvent(x, y, lastX, lastY); + } onUpEventInternal(lastX, lastY, eventTime); onDownEventInternal(x, y, eventTime); } else { diff --git a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java index 347383f95..107138395 100644 --- a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java +++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java @@ -22,7 +22,9 @@ import android.view.MotionEvent; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.define.ProductionFlag; public class SuddenJumpingTouchEventHandler { private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName(); @@ -141,6 +143,9 @@ public class SuddenJumpingTouchEventHandler { if (handleSuddenJumping(me)) { if (DEBUG_MODE) Log.w(TAG, "onTouchEvent: ignore sudden jump " + me); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.suddenJumpingTouchEventHandler_onTouchEvent(me); + } return true; } return mView.processMotionEvent(me); diff --git a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java index 5712df1fc..392afca97 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/AlphabetShiftState.java @@ -18,6 +18,9 @@ package com.android.inputmethod.keyboard.internal; import android.util.Log; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; + public class AlphabetShiftState { private static final String TAG = AlphabetShiftState.class.getSimpleName(); private static final boolean DEBUG = false; @@ -59,6 +62,9 @@ public class AlphabetShiftState { } if (DEBUG) Log.d(TAG, "setShifted(" + newShiftState + "): " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setShifted(newShiftState, oldState, this); + } } public void setShiftLocked(boolean newShiftLockState) { @@ -78,6 +84,9 @@ public class AlphabetShiftState { if (DEBUG) Log.d(TAG, "setShiftLocked(" + newShiftLockState + "): " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setShiftLocked(newShiftLockState, oldState, this); + } } public void setAutomaticShifted() { @@ -85,6 +94,9 @@ public class AlphabetShiftState { mState = AUTOMATIC_SHIFTED; if (DEBUG) Log.d(TAG, "setAutomaticShifted: " + toString(oldState) + " > " + this); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.alphabetShiftState_setAutomaticShifted(oldState, this); + } } public boolean isShiftedOrShiftLocked() { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java index 4abd887f0..288fb4556 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeySpecParser.java @@ -21,7 +21,6 @@ import android.text.TextUtils; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StringUtils; import java.util.ArrayList; @@ -33,9 +32,11 @@ import java.util.Arrays; * - String resource can be embedded into specification @string/name. This is done before parsing * comma. * Each "more key" specification is one of the following: - * - A single letter (Letter) * - Label optionally followed by keyOutputText or code (keyLabel|keyOutputText). - * - Icon followed by keyOutputText or code (@icon/icon_name|@integer/key_code) + * - Icon followed by keyOutputText or code (!icon/icon_name|!code/code_name) + * - Icon should be a string representation of icon (!icon/icon_name). + * - Code should be a code point presented by hexadecimal string prefixed with "0x". + * Or a string representation of code (!code/code_name). * Special character, comma ',' backslash '\', and bar '|' can be escaped by '\' character. * Note that the character '@' and '\' are also parsed by XML parser and CSV parser as well. * See {@link KeyboardIconsSet} about icon_name. @@ -52,10 +53,25 @@ public class KeySpecParser { private static final char SUFFIX_SLASH = '/'; private static final String PREFIX_STRING = PREFIX_AT + "string" + SUFFIX_SLASH; private static final char LABEL_END = '|'; - private static final String PREFIX_ICON = PREFIX_AT + "icon" + SUFFIX_SLASH; - private static final String PREFIX_CODE = PREFIX_AT + "integer" + SUFFIX_SLASH; + private static final String PREFIX_ICON = "!icon/"; + private static final String PREFIX_CODE = "!code/"; + private static final String PREFIX_HEX = "0x"; private static final String ADDITIONAL_MORE_KEY_MARKER = "%"; + public static class MoreKeySpec { + public final int mCode; + public final String mLabel; + public final String mOutputText; + public final int mIconId; + + public MoreKeySpec(final String moreKeySpec, final KeyboardCodesSet codesSet) { + mCode = getCode(moreKeySpec, codesSet); + mLabel = getLabel(moreKeySpec); + mOutputText = getOutputText(moreKeySpec); + mIconId = getIconId(moreKeySpec); + } + } + private KeySpecParser() { // Intentional empty constructor for utility class. } @@ -144,7 +160,7 @@ public class KeySpecParser { return parseEscape(moreKeySpec.substring(end + /* LABEL_END */1)); } - public static String getOutputText(String moreKeySpec) { + private static String getOutputText(String moreKeySpec) { if (hasCode(moreKeySpec)) { return null; } @@ -168,17 +184,13 @@ public class KeySpecParser { return (StringUtils.codePointCount(label) == 1) ? null : label; } - public static int getCode(Resources res, String moreKeySpec) { + private static int getCode(String moreKeySpec, KeyboardCodesSet codesSet) { if (hasCode(moreKeySpec)) { final int end = indexOfLabelEnd(moreKeySpec, 0); if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) { throw new KeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); } - final int resId = getResourceId(res, - moreKeySpec.substring(end + /* LABEL_END */1 + /* PREFIX_AT */1), - R.string.english_ime_name); - final int code = res.getInteger(resId); - return code; + return parseCode(moreKeySpec.substring(end + 1), codesSet, Keyboard.CODE_UNSPECIFIED); } final String outputText = getOutputTextInternal(moreKeySpec); if (outputText != null) { @@ -197,7 +209,18 @@ public class KeySpecParser { return Keyboard.CODE_OUTPUT_TEXT; } - public static int getIconId(String moreKeySpec) { + public static int parseCode(String text, KeyboardCodesSet codesSet, int defCode) { + if (text == null) return defCode; + if (text.startsWith(PREFIX_CODE)) { + return codesSet.getCode(text.substring(PREFIX_CODE.length())); + } else if (text.startsWith(PREFIX_HEX)) { + return Integer.parseInt(text.substring(PREFIX_HEX.length()), 16); + } else { + return Integer.parseInt(text); + } + } + + private static int getIconId(String moreKeySpec) { if (hasIcon(moreKeySpec)) { final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length()); final String name = moreKeySpec.substring(PREFIX_ICON.length(), end); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java index 9e5c227eb..405b7ad05 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java @@ -102,8 +102,8 @@ public class KeyStyles { void readKeyAttributes(TypedArray keyAttr) { // TODO: Currently not all Key attributes can be declared as style. - readInt(keyAttr, R.styleable.Keyboard_Key_code); - readInt(keyAttr, R.styleable.Keyboard_Key_altCode); + readString(keyAttr, R.styleable.Keyboard_Key_code); + readString(keyAttr, R.styleable.Keyboard_Key_altCode); readString(keyAttr, R.styleable.Keyboard_Key_keyLabel); readString(keyAttr, R.styleable.Keyboard_Key_keyOutputText); readString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java new file mode 100644 index 000000000..736a96c56 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import com.android.inputmethod.keyboard.Keyboard; + +import java.util.HashMap; + +public class KeyboardCodesSet { + private static final HashMap<String, int[]> sLanguageToCodesMap = + new HashMap<String, int[]>(); + private static final HashMap<String, Integer> sNameToIdMap = new HashMap<String, Integer>(); + + private int[] mCodes = DEFAULT; + + public void setLanguage(final String language) { + final int[] codes = sLanguageToCodesMap.get(language); + mCodes = (codes != null) ? codes : DEFAULT; + } + + public int getCode(final String name) { + final Integer id = sNameToIdMap.get(name); + if (id == null) throw new RuntimeException("Unknown key code: " + name); + return mCodes[id]; + } + + private static final String[] ID_TO_NAME = { + "key_tab", + "key_enter", + "key_space", + "key_shift", + "key_switch_alpha_symbol", + "key_output_text", + "key_delete", + "key_settings", + "key_shortcut", + "key_action_enter", + "key_action_next", + "key_action_previous", + "key_language_switch", + "key_unspecified", + "key_left_parenthesis", + "key_right_parenthesis", + "key_less_than", + "key_greater_than", + "key_left_square_bracket", + "key_right_square_bracket", + "key_left_curly_bracket", + "key_right_curly_bracket", + }; + + private static final int CODE_LEFT_PARENTHESIS = '('; + private static final int CODE_RIGHT_PARENTHESIS = ')'; + private static final int CODE_LESS_THAN_SIGN = '<'; + private static final int CODE_GREATER_THAN_SIGN = '>'; + private static final int CODE_LEFT_SQUARE_BRACKET = '['; + private static final int CODE_RIGHT_SQUARE_BRACKET = ']'; + private static final int CODE_LEFT_CURLY_BRACKET = '{'; + private static final int CODE_RIGHT_CURLY_BRACKET = '}'; + + private static final int[] DEFAULT = { + Keyboard.CODE_TAB, + Keyboard.CODE_ENTER, + Keyboard.CODE_SPACE, + Keyboard.CODE_SHIFT, + Keyboard.CODE_SWITCH_ALPHA_SYMBOL, + Keyboard.CODE_OUTPUT_TEXT, + Keyboard.CODE_DELETE, + Keyboard.CODE_SETTINGS, + Keyboard.CODE_SHORTCUT, + Keyboard.CODE_ACTION_ENTER, + Keyboard.CODE_ACTION_NEXT, + Keyboard.CODE_ACTION_PREVIOUS, + Keyboard.CODE_LANGUAGE_SWITCH, + Keyboard.CODE_UNSPECIFIED, + CODE_LEFT_PARENTHESIS, + CODE_RIGHT_PARENTHESIS, + CODE_LESS_THAN_SIGN, + CODE_GREATER_THAN_SIGN, + CODE_LEFT_SQUARE_BRACKET, + CODE_RIGHT_SQUARE_BRACKET, + CODE_LEFT_CURLY_BRACKET, + CODE_RIGHT_CURLY_BRACKET, + }; + + private static final int[] RTL = { + DEFAULT[0], + DEFAULT[1], + DEFAULT[2], + DEFAULT[3], + DEFAULT[4], + DEFAULT[5], + DEFAULT[6], + DEFAULT[7], + DEFAULT[8], + DEFAULT[9], + DEFAULT[10], + DEFAULT[11], + DEFAULT[12], + DEFAULT[13], + CODE_RIGHT_PARENTHESIS, + CODE_LEFT_PARENTHESIS, + CODE_GREATER_THAN_SIGN, + CODE_LESS_THAN_SIGN, + CODE_RIGHT_SQUARE_BRACKET, + CODE_LEFT_SQUARE_BRACKET, + CODE_RIGHT_CURLY_BRACKET, + CODE_LEFT_CURLY_BRACKET, + }; + + private static final String LANGUAGE_DEFAULT = "DEFAULT"; + private static final String LANGUAGE_ARABIC = "ar"; + private static final String LANGUAGE_PERSIAN = "fa"; + private static final String LANGUAGE_HEBREW = "iw"; + + private static final Object[] LANGUAGE_AND_CODES = { + LANGUAGE_DEFAULT, DEFAULT, + LANGUAGE_ARABIC, RTL, + LANGUAGE_PERSIAN, RTL, + LANGUAGE_HEBREW, RTL, + }; + + static { + for (int i = 0; i < ID_TO_NAME.length; i++) { + sNameToIdMap.put(ID_TO_NAME[i], i); + } + + for (int i = 0; i < LANGUAGE_AND_CODES.length; i += 2) { + final String language = (String)LANGUAGE_AND_CODES[i]; + final int[] codes = (int[])LANGUAGE_AND_CODES[i + 1]; + sLanguageToCodesMap.put(language, codes); + } + } +} diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 18a3f9794..6949c9d12 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -20,6 +20,8 @@ import android.text.TextUtils; import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.latin.ResearchLogger; +import com.android.inputmethod.latin.define.ProductionFlag; /** * Keyboard state machine. @@ -139,6 +141,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onSaveKeyboardState: saved=" + state + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onSaveKeyboardState(this, state.toString()); + } } private void onRestoreKeyboardState() { @@ -146,6 +151,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onRestoreKeyboardState: saved=" + state + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onRestoreKeyboardState(this, state.toString()); + } if (!state.mIsValid || state.mIsAlphabetMode) { setAlphabetKeyboard(); } else { @@ -178,6 +186,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setShifted(this, shiftModeToString(shiftMode)); + } if (!mIsAlphabetMode) return; final int prevShiftMode; if (mAlphabetShiftState.isAutomaticShifted()) { @@ -217,6 +228,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setShiftLocked: shiftLocked=" + shiftLocked + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setShiftLocked(this, shiftLocked); + } if (!mIsAlphabetMode) return; if (shiftLocked && (!mAlphabetShiftState.isShiftLocked() || mAlphabetShiftState.isShiftLockShifted())) { @@ -232,6 +246,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "toggleAlphabetAndSymbols: " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_toggleAlphabetAndSymbols(this); + } if (mIsAlphabetMode) { mPrevMainKeyboardWasShiftLocked = mAlphabetShiftState.isShiftLocked(); if (mPrevSymbolsKeyboardWasShifted) { @@ -262,6 +279,10 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setAlphabetKeyboard"); } + + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setAlphabetKeyboard(); + } mSwitchActions.setAlphabetKeyboard(); mIsAlphabetMode = true; mIsSymbolShifted = false; @@ -273,6 +294,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsKeyboard"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setSymbolsKeyboard(); + } mSwitchActions.setSymbolsKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = false; @@ -285,6 +309,9 @@ public class KeyboardState { if (DEBUG_ACTION) { Log.d(TAG, "setSymbolsShiftedKeyboard"); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_setSymbolsShiftedKeyboard(); + } mSwitchActions.setSymbolsShiftedKeyboard(); mIsAlphabetMode = false; mIsSymbolShifted = true; @@ -297,6 +324,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onPressKey(code, this); + } if (code == Keyboard.CODE_SHIFT) { onPressShift(); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -314,6 +344,9 @@ public class KeyboardState { Log.d(TAG, "onReleaseKey: code=" + Keyboard.printableCode(code) + " sliding=" + withSliding + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onReleaseKey(this, code, withSliding); + } if (code == Keyboard.CODE_SHIFT) { onReleaseShift(withSliding); } else if (code == Keyboard.CODE_SWITCH_ALPHA_SYMBOL) { @@ -345,6 +378,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onLongPressTimeout(code, this); + } if (mIsAlphabetMode && code == Keyboard.CODE_SHIFT) { if (mAlphabetShiftState.isShiftLocked()) { setShiftLocked(false); @@ -363,6 +399,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onUpdateShiftState(this, autoCaps); + } updateAlphabetShiftState(autoCaps); } @@ -481,6 +520,9 @@ public class KeyboardState { if (DEBUG_EVENT) { Log.d(TAG, "onCancelInput: single=" + isSinglePointer + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onCancelInput(isSinglePointer, this); + } // Switch back to the previous keyboard mode if the user cancels sliding input. if (isSinglePointer) { if (mSwitchState == SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL) { @@ -512,6 +554,9 @@ public class KeyboardState { + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.keyboardState_onCodeInput(code, isSinglePointer, autoCaps, this); + } switch (mSwitchState) { case SWITCH_STATE_MOMENTARY_ALPHA_AND_SYMBOL: diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index f5c09974e..e0fa2f838 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -665,6 +665,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions)); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onStartInputViewInternal(editorInfo); + } if (StringUtils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions); @@ -762,19 +765,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd); - if (ProductionFlag.IS_EXPERIMENTAL) { - if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) { - final String s = "onUpdateSelection: oss=" + oldSelStart - + ", ose=" + oldSelEnd - + ", lss=" + mLastSelectionStart - + ", lse=" + mLastSelectionEnd - + ", nss=" + newSelStart - + ", nse=" + newSelEnd - + ", cs=" + composingSpanStart - + ", ce=" + composingSpanEnd; - ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s); - } - } if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -785,6 +775,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd, + oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, + composingSpanEnd); + } // TODO: refactor the following code to be less contrived. // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means @@ -886,6 +881,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions); + } if (mInputAttributes.mApplicationSpecifiedCompletionOn) { mApplicationSpecifiedCompletions = applicationSpecifiedCompletions; if (applicationSpecifiedCompletions == null) { @@ -1660,6 +1658,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { Log.d(TAG, "Switch to keyboard view."); } + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.latinIME_switchToKeyboardView(); + } View v = mKeyboardSwitcher.getKeyboardView(); if (v != null) { // Confirms that the keyboard view doesn't have parent view. diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java index c5fb61f78..08c26a5df 100644 --- a/java/src/com/android/inputmethod/latin/ResearchLogger.java +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -25,15 +25,20 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; import android.view.MotionEvent; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.internal.AlphabetShiftState; +import com.android.inputmethod.keyboard.internal.KeyboardState; +import com.android.inputmethod.latin.define.ProductionFlag; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; -import java.text.SimpleDateFormat; -import java.util.Date; /** * Logs the use of the LatinIME keyboard. @@ -46,13 +51,12 @@ import java.util.Date; public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = ResearchLogger.class.getSimpleName(); private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + private static final boolean DEBUG = false; private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); public static boolean sIsLogging = false; /* package */ final Handler mLoggingHandler; private InputMethodService mIms; - private final Date mDate; - private final SimpleDateFormat mDateFormat; /** * Isolates management of files. This variable should never be null, but can be changed @@ -79,35 +83,36 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang /* package */ LogFileManager() { } - public void init(InputMethodService ims) { + public void init(final InputMethodService ims) { mIms = ims; } - public synchronized void createLogFile() { + public synchronized boolean createLogFile() { try { - createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); - } catch (FileNotFoundException e) { + return createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); + } catch (final FileNotFoundException e) { Log.w(TAG, e); + return false; } } - public synchronized void createLogFile(String dir, String filename) + public synchronized boolean createLogFile(final String dir, final String filename) throws FileNotFoundException { if (mIms == null) { Log.w(TAG, "InputMethodService is not configured. Logging is off."); - return; + return false; } - File filesDir = mIms.getFilesDir(); + final File filesDir = mIms.getFilesDir(); if (filesDir == null || !filesDir.exists()) { Log.w(TAG, "Storage directory does not exist. Logging is off."); - return; + return false; } - File directory = new File(filesDir, dir); + final File directory = new File(filesDir, dir); if (!directory.exists()) { - boolean wasCreated = directory.mkdirs(); + final boolean wasCreated = directory.mkdirs(); if (!wasCreated) { Log.w(TAG, "Log directory cannot be created. Logging is off."); - return; + return false; } } @@ -120,16 +125,23 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang append = false; } mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); + return true; } - public synchronized boolean append(String s) { + public synchronized boolean append(final String s) { if (mPrintWriter == null) { - Log.w(TAG, "PrintWriter is null"); - return false; - } else { - mPrintWriter.print(s); - return !mPrintWriter.checkError(); + if (DEBUG) { + Log.w(TAG, "PrintWriter is null... attempting to create default log file"); + } + if (!createLogFile()) { + if (DEBUG) { + Log.w(TAG, "Failed to create log file. Not logging."); + return false; + } + } } + mPrintWriter.print(s); + return !mPrintWriter.checkError(); } public synchronized void reset() { @@ -152,11 +164,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - private ResearchLogger(LogFileManager logFileManager) { - mDate = new Date(); - mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); - - HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", + private ResearchLogger(final LogFileManager logFileManager) { + final HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", Process.THREAD_PRIORITY_BACKGROUND); handlerThread.start(); mLoggingHandler = new Handler(handlerThread.getLooper()); @@ -167,11 +176,11 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return sInstance; } - public static void init(InputMethodService ims, SharedPreferences prefs) { + public static void init(final InputMethodService ims, final SharedPreferences prefs) { sInstance.initInternal(ims, prefs); } - public void initInternal(InputMethodService ims, SharedPreferences prefs) { + public void initInternal(final InputMethodService ims, final SharedPreferences prefs) { mIms = ims; if (mLogFileManager != null) { mLogFileManager.init(ims); @@ -188,7 +197,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang * * @throws IllegalArgumentException if logFileManager is null */ - void setLogFileManager(LogFileManager manager) { + void setLogFileManager(final LogFileManager manager) { if (manager == null) { throw new IllegalArgumentException("warning: trying to set null logFileManager"); } else { @@ -203,11 +212,12 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang MOTION_EVENT("m"), KEY("k"), CORRECTION("c"), - STATE_CHANGE("s"); + STATE_CHANGE("s"), + UNSTRUCTURED("u"); private final String mLogString; - private LogGroup(String logString) { + private LogGroup(final String logString) { mLogString = logString; } } @@ -226,7 +236,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang default: eventTag = "[Action" + action + "]"; break; } if (!TextUtils.isEmpty(eventTag)) { - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); sb.append(eventTag); sb.append('\t'); sb.append(eventTime); sb.append('\t'); sb.append(id); @@ -238,7 +248,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - public void logKeyEvent(int code, int x, int y) { + public void logKeyEvent(final int code, final int x, final int y) { final StringBuilder sb = new StringBuilder(); sb.append(Keyboard.printableCode(code)); sb.append('\t'); sb.append(x); @@ -246,7 +256,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.KEY, sb.toString()); } - public void logCorrection(String subgroup, String before, String after, int position) { + public void logCorrection(final String subgroup, final String before, final String after, + final int position) { final StringBuilder sb = new StringBuilder(); sb.append(subgroup); sb.append('\t'); sb.append(before); @@ -255,19 +266,58 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang write(LogGroup.CORRECTION, sb.toString()); } - public void logStateChange(String subgroup, String details) { + public void logStateChange(final String subgroup, final String details) { write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); } - public static enum UnsLogGroup { - // TODO: expand to include one flag per log point - // TODO: support selective enabling of flags - ON_UPDATE_SELECTION; - - public boolean isEnabled = true; + public static class UnsLogGroup { + private static final boolean DEFAULT_ENABLED = true; + + private static final boolean ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; + private static final boolean ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; + private static final boolean ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED + = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONCANCELINPUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONCODEINPUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONPRESSKEY_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONRELEASEKEY_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSHIFTED_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED + = DEFAULT_ENABLED; + private static final boolean KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED + = DEFAULT_ENABLED; + private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED = DEFAULT_ENABLED; + private static final boolean LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED + = DEFAULT_ENABLED; + private static final boolean + POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED + = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_ONDOWNEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean POINTERTRACKER_ONMOVEEVENT_ENABLED = DEFAULT_ENABLED; + private static final boolean SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED + = DEFAULT_ENABLED; + private static final boolean SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED = DEFAULT_ENABLED; } - public static void logUnstructured(UnsLogGroup logGroup, String details) { + public static void logUnstructured(String logGroup, final String details) { + // TODO: improve performance by making entire class static and/or implementing natively + getInstance().write(LogGroup.UNSTRUCTURED, logGroup + "\t" + details); } private void write(final LogGroup logGroup, final String log) { @@ -282,13 +332,14 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang builder.append('\t'); builder.append(upTime); builder.append('\t'); builder.append(logGroup.mLogString); builder.append('\t'); builder.append(log); - if (LatinImeLogger.sDBG) { + builder.append('\n'); + if (DEBUG) { Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); } if (mLogFileManager.append(builder.toString())) { // success } else { - if (LatinImeLogger.sDBG) { + if (DEBUG) { Log.w(TAG, "Unable to write to log."); } } @@ -300,7 +351,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang mLoggingHandler.post(new Runnable() { @Override public void run() { - if (LatinImeLogger.sDBG) { + if (DEBUG) { Log.d(TAG, "Delete log file."); } mLogFileManager.reset(); @@ -315,4 +366,287 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); } + + public static void alphabetShiftState_setShifted(final boolean newShiftState, + final int oldState, final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTED_ENABLED) { + final String s = "setShifted(" + newShiftState + "): " + oldState + + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setShifted", s); + } + } + + public static void alphabetShiftState_setShiftLocked(final boolean newShiftLockState, + final int oldState, final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETSHIFTLOCKED_ENABLED) { + final String s = "setShiftLocked(" + newShiftLockState + "): " + + oldState + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setShiftLocked", s); + } + } + + public static void alphabetShiftState_setAutomaticShifted(final int oldState, + final AlphabetShiftState alphabetShiftState) { + if (UnsLogGroup.ALPHABETSHIFTSTATE_SETAUTOMATICSHIFTED_ENABLED) { + final String s = "setAutomaticShifted: " + oldState + " > " + alphabetShiftState; + logUnstructured("AlphabetShiftState_setAutomaticShifted", s); + } + } + + public static void keyboardState_onCancelInput(final boolean isSinglePointer, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONCANCELINPUT_ENABLED) { + final String s = "onCancelInput: single=" + isSinglePointer + " " + keyboardState; + logUnstructured("KeyboardState_onCancelInput", s); + } + } + + public static void keyboardState_onCodeInput( + final int code, final boolean isSinglePointer, final boolean autoCaps, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) { + final String s = "onCodeInput: code=" + Keyboard.printableCode(code) + + " single=" + isSinglePointer + + " autoCaps=" + autoCaps + " " + keyboardState; + logUnstructured("KeyboardState_onCodeInput", s); + } + } + + public static void keyboardState_onLongPressTimeout(final int code, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONLONGPRESSTIMEOUT_ENABLED) { + final String s = "onLongPressTimeout: code=" + Keyboard.printableCode(code) + " " + + keyboardState; + logUnstructured("KeyboardState_onLongPressTimeout", s); + } + } + + public static void keyboardState_onPressKey(final int code, + final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONPRESSKEY_ENABLED) { + final String s = "onPressKey: code=" + Keyboard.printableCode(code) + " " + + keyboardState; + logUnstructured("KeyboardState_onPressKey", s); + } + } + + public static void keyboardState_onReleaseKey(final KeyboardState keyboardState, final int code, + final boolean withSliding) { + if (UnsLogGroup.KEYBOARDSTATE_ONRELEASEKEY_ENABLED) { + final String s = "onReleaseKey: code=" + Keyboard.printableCode(code) + + " sliding=" + withSliding + " " + keyboardState; + logUnstructured("KeyboardState_onReleaseKey", s); + } + } + + public static void keyboardState_onRestoreKeyboardState(final KeyboardState keyboardState, + final String savedKeyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONRESTOREKEYBOARDSTATE_ENABLED) { + final String s = "onRestoreKeyboardState: saved=" + savedKeyboardState + " " + + keyboardState; + logUnstructured("KeyboardState_onRestoreKeyboardState", s); + } + } + + public static void keyboardState_onSaveKeyboardState(final KeyboardState keyboardState, + final String savedKeyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_ONSAVEKEYBOARDSTATE_ENABLED) { + final String s = "onSaveKeyboardState: saved=" + savedKeyboardState + " " + + keyboardState; + logUnstructured("KeyboardState_onSaveKeyboardState", s); + } + } + + public static void keyboardState_onUpdateShiftState(final KeyboardState keyboardState, + final boolean autoCaps) { + if (UnsLogGroup.KEYBOARDSTATE_ONUPDATESHIFTSTATE_ENABLED) { + final String s = "onUpdateShiftState: autoCaps=" + autoCaps + " " + keyboardState; + logUnstructured("KeyboardState_onUpdateShiftState", s); + } + } + + public static void keyboardState_setAlphabetKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETALPHABETKEYBOARD_ENABLED) { + final String s = "setAlphabetKeyboard"; + logUnstructured("KeyboardState_setAlphabetKeyboard", s); + } + } + + public static void keyboardState_setShifted(final KeyboardState keyboardState, + final String shiftMode) { + if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTED_ENABLED) { + final String s = "setShifted: shiftMode=" + shiftMode + " " + keyboardState; + logUnstructured("KeyboardState_setShifted", s); + } + } + + public static void keyboardState_setShiftLocked(final KeyboardState keyboardState, + final boolean shiftLocked) { + if (UnsLogGroup.KEYBOARDSTATE_SETSHIFTLOCKED_ENABLED) { + final String s = "setShiftLocked: shiftLocked=" + shiftLocked + " " + keyboardState; + logUnstructured("KeyboardState_setShiftLocked", s); + } + } + + public static void keyboardState_setSymbolsKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSKEYBOARD_ENABLED) { + final String s = "setSymbolsKeyboard"; + logUnstructured("KeyboardState_setSymbolsKeyboard", s); + } + } + + public static void keyboardState_setSymbolsShiftedKeyboard() { + if (UnsLogGroup.KEYBOARDSTATE_SETSYMBOLSSHIFTEDKEYBOARD_ENABLED) { + final String s = "setSymbolsShiftedKeyboard"; + logUnstructured("KeyboardState_setSymbolsShiftedKeyboard", s); + } + } + + public static void keyboardState_toggleAlphabetAndSymbols(final KeyboardState keyboardState) { + if (UnsLogGroup.KEYBOARDSTATE_TOGGLEALPHABETANDSYMBOLS_ENABLED) { + final String s = "toggleAlphabetAndSymbols: " + keyboardState; + logUnstructured("KeyboardState_toggleAlphabetAndSymbols", s); + } + } + + public static void latinIME_onDisplayCompletions( + final CompletionInfo[] applicationSpecifiedCompletions) { + if (UnsLogGroup.LATINIME_ONDISPLAYCOMPLETIONS_ENABLED) { + final StringBuilder builder = new StringBuilder(); + builder.append("Received completions:"); + if (applicationSpecifiedCompletions != null) { + for (int i = 0; i < applicationSpecifiedCompletions.length; i++) { + builder.append(" #"); + builder.append(i); + builder.append(": "); + builder.append(applicationSpecifiedCompletions[i]); + builder.append("\n"); + } + } + logUnstructured("LatinIME_onDisplayCompletions", builder.toString()); + } + } + + public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo) { + if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) { + final StringBuilder builder = new StringBuilder(); + builder.append("onStartInputView: editorInfo:"); + builder.append("inputType="); + builder.append(editorInfo.inputType); + builder.append("imeOptions="); + builder.append(editorInfo.imeOptions); + logUnstructured("LatinIME_onStartInputViewInternal", builder.toString()); + } + } + + public static void latinIME_onUpdateSelection(final int lastSelectionStart, + final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd, + final int newSelStart, final int newSelEnd, final int composingSpanStart, + final int composingSpanEnd) { + if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) { + final String s = "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", lss=" + lastSelectionStart + + ", lse=" + lastSelectionEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd; + logUnstructured("LatinIME_onUpdateSelection", s); + } + } + + public static void latinIME_switchToKeyboardView() { + if (UnsLogGroup.LATINIME_SWITCHTOKEYBOARDVIEW_ENABLED) { + final String s = "Switch to keyboard view."; + logUnstructured("LatinIME_switchToKeyboardView", s); + } + } + + public static void latinKeyboardView_onLongPress() { + if (UnsLogGroup.LATINKEYBOARDVIEW_ONLONGPRESS_ENABLED) { + final String s = "long press detected"; + logUnstructured("LatinKeyboardView_onLongPress", s); + } + } + + public static void latinKeyboardView_processMotionEvent(MotionEvent me, int action, + long eventTime, int index, int id, int x, int y) { + if (UnsLogGroup.LATINKEYBOARDVIEW_ONPROCESSMOTIONEVENT_ENABLED) { + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + getInstance().logMotionEvent(action, eventTime, id, x, y, size, pressure); + } + } + } + + public static void pointerTracker_callListenerOnCancelInput() { + final String s = "onCancelInput"; + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCANCELINPUT_ENABLED) { + logUnstructured("PointerTracker_callListenerOnCancelInput", s); + } + } + + public static void pointerTracker_callListenerOnCodeInput(final Key key, final int x, + final int y, final boolean ignoreModifierKey, final boolean altersCode, + final int code) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONCODEINPUT_ENABLED) { + final String s = "onCodeInput: " + Keyboard.printableCode(code) + + " text=" + key.mOutputText + " x=" + x + " y=" + y + + " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode + + " enabled=" + key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnCodeInput", s); + } + } + + public static void pointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange( + final Key key, final boolean ignoreModifierKey) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONPRESSANDCHECKKEYBOARDLAYOUTCHANGE_ENABLED) { + final String s = "onPress : " + KeyDetector.printableCode(key) + + " ignoreModifier=" + ignoreModifierKey + + " enabled=" + key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnPressAndCheckKeyboardLayoutChange", s); + } + } + + public static void pointerTracker_callListenerOnRelease(final Key key, final int primaryCode, + final boolean withSliding, final boolean ignoreModifierKey) { + if (UnsLogGroup.POINTERTRACKER_CALLLISTENERONRELEASE_ENABLED) { + final String s = "onRelease : " + Keyboard.printableCode(primaryCode) + + " sliding=" + withSliding + " ignoreModifier=" + ignoreModifierKey + + " enabled="+ key.isEnabled(); + logUnstructured("PointerTracker_callListenerOnRelease", s); + } + } + + public static void pointerTracker_onDownEvent(long deltaT, int distanceSquared) { + if (UnsLogGroup.POINTERTRACKER_ONDOWNEVENT_ENABLED) { + final String s = "onDownEvent: ignore potential noise: time=" + deltaT + + " distance=" + distanceSquared; + logUnstructured("PointerTracker_onDownEvent", s); + } + } + + public static void pointerTracker_onMoveEvent(final int x, final int y, final int lastX, + final int lastY) { + if (UnsLogGroup.POINTERTRACKER_ONMOVEEVENT_ENABLED) { + final String s = String.format("onMoveEvent: sudden move is translated to " + + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y); + logUnstructured("PointerTracker_onMoveEvent", s); + } + } + + public static void suddenJumpingTouchEventHandler_onTouchEvent(final MotionEvent me) { + if (UnsLogGroup.SUDDENJUMPINGTOUCHEVENTHANDLER_ONTOUCHEVENT_ENABLED) { + final String s = "onTouchEvent: ignore sudden jump " + me; + logUnstructured("SuddenJumpingTouchEventHandler_onTouchEvent", s); + } + } + + public static void suggestionsView_setSuggestions(SuggestedWords mSuggestedWords) { + if (UnsLogGroup.SUGGESTIONSVIEW_SETSUGGESTIONS_ENABLED) { + logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString()); + } + } } diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index 1ad37b933..01d51d463 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -59,10 +59,12 @@ import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.ViewLayoutUtils; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.ResearchLogger; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.Suggest; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.Utils; +import com.android.inputmethod.latin.define.ProductionFlag; import java.util.ArrayList; @@ -663,6 +665,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, clear(); mSuggestedWords = suggestedWords; mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth()); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.suggestionsView_setSuggestions(mSuggestedWords); + } } public int setMoreSuggestionsHeight(int remainingHeight) { |