upload android base code part8

This commit is contained in:
August 2018-08-08 20:10:12 +08:00
parent 841ae54672
commit 5425409085
57075 changed files with 9846578 additions and 0 deletions

View file

@ -0,0 +1,16 @@
# Copyright (C) 2013 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.
subdirs := common native java tests tools
include $(call all-named-subdir-makefiles, $(subdirs))

View file

@ -0,0 +1,57 @@
# Copyright (C) 2007 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.
#
# If you don't need to do a full clean build but would like to touch
# a file or delete some intermediate files, add a clean step to the end
# of the list. These steps will only be run once, if they haven't been
# run before.
#
# E.g.:
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
#
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
# files that are missing or have been moved.
#
# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
# Use $(OUT_DIR) to refer to the "out" directory.
#
# If you need to re-do something that's already mentioned, just copy
# the command and add it to the bottom of the list. E.g., if a change
# that you made last week required touching a file and a change you
# made today requires touching the same file, just copy the old
# touch step and add it to the end of the list.
#
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
# For example:
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/LatinIME*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/LatinIME.apk)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************

View file

@ -0,0 +1,28 @@
# Copyright (C) 2014 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.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := latinime-common
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := jsr305
LOCAL_SDK_VERSION := 21
include $(BUILD_STATIC_JAVA_LIBRARY)
# Also build a host side library
include $(CLEAR_VARS)
LOCAL_MODULE := latinime-common-host
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_STATIC_JAVA_LIBRARIES := jsr305lib
include $(BUILD_HOST_JAVA_LIBRARY)

View file

@ -0,0 +1,24 @@
/*
* 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.annotations;
/**
* Denotes that the class, method or field should not be eliminated by ProGuard,
* because it is externally referenced. (See proguard.flags)
*/
public @interface ExternallyReferenced {
}

View file

@ -0,0 +1,24 @@
/*
* 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.annotations;
/**
* Denotes that the class, method or field should not be eliminated by ProGuard,
* so that unit tests can access it. (See proguard.flags)
*/
public @interface UsedForTesting {
}

View file

@ -0,0 +1,117 @@
/*
* Copyright (C) 2013 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.latin.common;
import com.android.inputmethod.annotations.UsedForTesting;
import java.util.Random;
import javax.annotation.Nonnull;
// Utility methods related with code points used for tests.
// TODO: Figure out where this class should be.
@UsedForTesting
public class CodePointUtils {
private CodePointUtils() {
// This utility class is not publicly instantiable.
}
public static final int[] LATIN_ALPHABETS_LOWER = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
0x00E0 /* LATIN SMALL LETTER A WITH GRAVE */,
0x00E1 /* LATIN SMALL LETTER A WITH ACUTE */,
0x00E2 /* LATIN SMALL LETTER A WITH CIRCUMFLEX */,
0x00E3 /* LATIN SMALL LETTER A WITH TILDE */,
0x00E4 /* LATIN SMALL LETTER A WITH DIAERESIS */,
0x00E5 /* LATIN SMALL LETTER A WITH RING ABOVE */,
0x00E6 /* LATIN SMALL LETTER AE */,
0x00E7 /* LATIN SMALL LETTER C WITH CEDILLA */,
0x00E8 /* LATIN SMALL LETTER E WITH GRAVE */,
0x00E9 /* LATIN SMALL LETTER E WITH ACUTE */,
0x00EA /* LATIN SMALL LETTER E WITH CIRCUMFLEX */,
0x00EB /* LATIN SMALL LETTER E WITH DIAERESIS */,
0x00EC /* LATIN SMALL LETTER I WITH GRAVE */,
0x00ED /* LATIN SMALL LETTER I WITH ACUTE */,
0x00EE /* LATIN SMALL LETTER I WITH CIRCUMFLEX */,
0x00EF /* LATIN SMALL LETTER I WITH DIAERESIS */,
0x00F0 /* LATIN SMALL LETTER ETH */,
0x00F1 /* LATIN SMALL LETTER N WITH TILDE */,
0x00F2 /* LATIN SMALL LETTER O WITH GRAVE */,
0x00F3 /* LATIN SMALL LETTER O WITH ACUTE */,
0x00F4 /* LATIN SMALL LETTER O WITH CIRCUMFLEX */,
0x00F5 /* LATIN SMALL LETTER O WITH TILDE */,
0x00F6 /* LATIN SMALL LETTER O WITH DIAERESIS */,
0x00F7 /* LATIN SMALL LETTER O WITH STROKE */,
0x00F9 /* LATIN SMALL LETTER U WITH GRAVE */,
0x00FA /* LATIN SMALL LETTER U WITH ACUTE */,
0x00FB /* LATIN SMALL LETTER U WITH CIRCUMFLEX */,
0x00FC /* LATIN SMALL LETTER U WITH DIAERESIS */,
0x00FD /* LATIN SMALL LETTER Y WITH ACUTE */,
0x00FE /* LATIN SMALL LETTER THORN */,
0x00FF /* LATIN SMALL LETTER Y WITH DIAERESIS */
};
@UsedForTesting
@Nonnull
public static int[] generateCodePointSet(final int codePointSetSize,
@Nonnull final Random random) {
final int[] codePointSet = new int[codePointSetSize];
for (int i = codePointSet.length - 1; i >= 0; ) {
final int r = Math.abs(random.nextInt());
if (r < 0) {
continue;
}
// Don't insert 0~0x20, but insert any other code point.
// Code points are in the range 0~0x10FFFF.
final int candidateCodePoint = 0x20 + r % (Character.MAX_CODE_POINT - 0x20);
// Code points between MIN_ and MAX_SURROGATE are not valid on their own.
if (candidateCodePoint >= Character.MIN_SURROGATE
&& candidateCodePoint <= Character.MAX_SURROGATE) {
continue;
}
codePointSet[i] = candidateCodePoint;
--i;
}
return codePointSet;
}
/**
* Generates a random word.
*/
@UsedForTesting
@Nonnull
public static String generateWord(@Nonnull final Random random,
@Nonnull final int[] codePointSet) {
final StringBuilder builder = new StringBuilder();
// 8 * 4 = 32 chars max, but we do it the following way so as to bias the random toward
// longer words. This should be closer to natural language, and more importantly, it will
// exercise the algorithms in dicttool much more.
final int count = 1 + (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5)
+ (Math.abs(random.nextInt()) % 5);
while (builder.length() < count) {
builder.appendCodePoint(codePointSet[Math.abs(random.nextInt()) % codePointSet.length]);
}
return builder.toString();
}
}

View file

@ -0,0 +1,77 @@
/*
* 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.latin.common;
import com.android.inputmethod.annotations.UsedForTesting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Utility methods for working with collections.
*/
public final class CollectionUtils {
private CollectionUtils() {
// This utility class is not publicly instantiable.
}
/**
* Converts a sub-range of the given array to an ArrayList of the appropriate type.
* @param array Array to be converted.
* @param start First index inclusive to be converted.
* @param end Last index exclusive to be converted.
* @throws IllegalArgumentException if start or end are out of range or start &gt; end.
*/
@Nonnull
public static <E> ArrayList<E> arrayAsList(@Nonnull final E[] array, final int start,
final int end) {
if (start < 0 || start > end || end > array.length) {
throw new IllegalArgumentException("Invalid start: " + start + " end: " + end
+ " with array.length: " + array.length);
}
final ArrayList<E> list = new ArrayList<>(end - start);
for (int i = start; i < end; i++) {
list.add(array[i]);
}
return list;
}
/**
* Tests whether c contains no elements, true if c is null or c is empty.
* @param c Collection to test.
* @return Whether c contains no elements.
*/
@UsedForTesting
public static boolean isNullOrEmpty(@Nullable final Collection c) {
return c == null || c.isEmpty();
}
/**
* Tests whether map contains no elements, true if map is null or map is empty.
* @param map Map to test.
* @return Whether map contains no elements.
*/
@UsedForTesting
public static boolean isNullOrEmpty(@Nullable final Map map) {
return map == null || map.isEmpty();
}
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2014 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.latin.common;
import javax.annotation.Nonnull;
/**
* An immutable class that encapsulates a snapshot of word composition data.
*/
public class ComposedData {
@Nonnull
public final InputPointers mInputPointers;
public final boolean mIsBatchMode;
@Nonnull
public final String mTypedWord;
public ComposedData(@Nonnull final InputPointers inputPointers, final boolean isBatchMode,
@Nonnull final String typedWord) {
mInputPointers = inputPointers;
mIsBatchMode = isBatchMode;
mTypedWord = typedWord;
}
/**
* Copy the code points in the typed word to a destination array of ints.
*
* If the array is too small to hold the code points in the typed word, nothing is copied and
* -1 is returned.
*
* @param destination the array of ints.
* @return the number of copied code points.
*/
public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
@Nonnull final int[] destination) {
// lastIndex is exclusive
final int lastIndex = mTypedWord.length()
- StringUtils.getTrailingSingleQuotesCount(mTypedWord);
if (lastIndex <= 0) {
// The string is empty or contains only single quotes.
return 0;
}
// The following function counts the number of code points in the text range which begins
// at index 0 and extends to the character at lastIndex.
final int codePointSize = Character.codePointCount(mTypedWord, 0, lastIndex);
if (codePointSize > destination.length) {
return -1;
}
return StringUtils.copyCodePointsAndReturnCodePointCount(destination, mTypedWord, 0,
lastIndex, true /* downCase */);
}
}

View file

@ -0,0 +1,335 @@
/*
* 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.latin.common;
import com.android.inputmethod.annotations.UsedForTesting;
import javax.annotation.Nonnull;
public final class Constants {
public static final class Color {
/**
* The alpha value for fully opaque.
*/
public final static int ALPHA_OPAQUE = 255;
}
public static final class ImeOption {
/**
* The private IME option used to indicate that no microphone should be shown for a given
* text field. For instance, this is specified by the search dialog when the dialog is
* already showing a voice search button.
*
* @deprecated Use {@link ImeOption#NO_MICROPHONE} with package name prefixed.
*/
@SuppressWarnings("dep-ann")
public static final String NO_MICROPHONE_COMPAT = "nm";
/**
* The private IME option used to indicate that no microphone should be shown for a given
* text field. For instance, this is specified by the search dialog when the dialog is
* already showing a voice search button.
*/
public static final String NO_MICROPHONE = "noMicrophoneKey";
/**
* The private IME option used to indicate that no settings key should be shown for a given
* text field.
*/
public static final String NO_SETTINGS_KEY = "noSettingsKey";
/**
* The private IME option used to indicate that the given text field needs ASCII code points
* input.
*
* @deprecated Use EditorInfo#IME_FLAG_FORCE_ASCII.
*/
@SuppressWarnings("dep-ann")
public static final String FORCE_ASCII = "forceAscii";
/**
* The private IME option used to suppress the floating gesture preview for a given text
* field. This overrides the corresponding keyboard settings preference.
* {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled}
*/
public static final String NO_FLOATING_GESTURE_PREVIEW = "noGestureFloatingPreview";
private ImeOption() {
// This utility class is not publicly instantiable.
}
}
public static final class Subtype {
/**
* The subtype mode used to indicate that the subtype is a keyboard.
*/
public static final String KEYBOARD_MODE = "keyboard";
public static final class ExtraValue {
/**
* The subtype extra value used to indicate that this subtype is capable of
* entering ASCII characters.
*/
public static final String ASCII_CAPABLE = "AsciiCapable";
/**
* The subtype extra value used to indicate that this subtype is enabled
* when the default subtype is not marked as ascii capable.
*/
public static final String ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE =
"EnabledWhenDefaultIsNotAsciiCapable";
/**
* The subtype extra value used to indicate that this subtype is capable of
* entering emoji characters.
*/
public static final String EMOJI_CAPABLE = "EmojiCapable";
/**
* The subtype extra value used to indicate that this subtype requires a network
* connection to work.
*/
public static final String REQ_NETWORK_CONNECTIVITY = "requireNetworkConnectivity";
/**
* The subtype extra value used to indicate that the display name of this subtype
* contains a "%s" for printf-like replacement and it should be replaced by
* this extra value.
* This extra value is supported on JellyBean and later.
*/
public static final String UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME =
"UntranslatableReplacementStringInSubtypeName";
/**
* The subtype extra value used to indicate this subtype keyboard layout set name.
* This extra value is private to LatinIME.
*/
public static final String KEYBOARD_LAYOUT_SET = "KeyboardLayoutSet";
/**
* The subtype extra value used to indicate that this subtype is an additional subtype
* that the user defined. This extra value is private to LatinIME.
*/
public static final String IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
/**
* The subtype extra value used to specify the combining rules.
*/
public static final String COMBINING_RULES = "CombiningRules";
private ExtraValue() {
// This utility class is not publicly instantiable.
}
}
private Subtype() {
// This utility class is not publicly instantiable.
}
}
public static final class TextUtils {
/**
* Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
* characters. This value may be used with
* {@link android.text.TextUtils#CAP_MODE_CHARACTERS},
* {@link android.text.TextUtils#CAP_MODE_WORDS}, and
* {@link android.text.TextUtils#CAP_MODE_SENTENCES}.
*/
// TODO: Straighten this out. It's bizarre to have to use android.text.TextUtils.CAP_MODE_*
// except for OFF that is in Constants.TextUtils.
public static final int CAP_MODE_OFF = 0;
private TextUtils() {
// This utility class is not publicly instantiable.
}
}
public static final int NOT_A_CODE = -1;
public static final int NOT_A_CURSOR_POSITION = -1;
// TODO: replace the following constants with state in InputTransaction?
public static final int NOT_A_COORDINATE = -1;
public static final int SUGGESTION_STRIP_COORDINATE = -2;
public static final int EXTERNAL_KEYBOARD_COORDINATE = -4;
// A hint on how many characters to cache from the TextView. A good value of this is given by
// how many characters we need to be able to almost always find the caps mode.
public static final int EDITOR_CONTENTS_CACHE_SIZE = 1024;
// How many characters we accept for the recapitalization functionality. This needs to be
// large enough for all reasonable purposes, but avoid purposeful attacks. 100k sounds about
// right for this.
public static final int MAX_CHARACTERS_FOR_RECAPITALIZATION = 1024 * 100;
// Key events coming any faster than this are long-presses.
public static final int LONG_PRESS_MILLISECONDS = 200;
// TODO: Set this value appropriately.
public static final int GET_SUGGESTED_WORDS_TIMEOUT = 200;
// How many continuous deletes at which to start deleting at a higher speed.
public static final int DELETE_ACCELERATE_AT = 20;
public static final String WORD_SEPARATOR = " ";
public static boolean isValidCoordinate(final int coordinate) {
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
// and {@link SPELL_CHECKER_COORDINATE}.
return coordinate >= 0;
}
/**
* Custom request code used in
* {@link com.android.inputmethod.keyboard.KeyboardActionListener#onCustomRequest(int)}.
*/
// The code to show input method picker.
public static final int CUSTOM_CODE_SHOW_INPUT_METHOD_PICKER = 1;
/**
* Some common keys code. Must be positive.
*/
public static final int CODE_ENTER = '\n';
public static final int CODE_TAB = '\t';
public static final int CODE_SPACE = ' ';
public static final int CODE_PERIOD = '.';
public static final int CODE_COMMA = ',';
public static final int CODE_DASH = '-';
public static final int CODE_SINGLE_QUOTE = '\'';
public static final int CODE_DOUBLE_QUOTE = '"';
public static final int CODE_SLASH = '/';
public static final int CODE_BACKSLASH = '\\';
public static final int CODE_VERTICAL_BAR = '|';
public static final int CODE_COMMERCIAL_AT = '@';
public static final int CODE_PLUS = '+';
public static final int CODE_PERCENT = '%';
public static final int CODE_CLOSING_PARENTHESIS = ')';
public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
public static final int CODE_CLOSING_CURLY_BRACKET = '}';
public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿
public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡
public static final int CODE_GRAVE_ACCENT = '`';
public static final int CODE_CIRCUMFLEX_ACCENT = '^';
public static final int CODE_TILDE = '~';
public static final String REGEXP_PERIOD = "\\.";
public static final String STRING_SPACE = " ";
/**
* Special keys code. Must be negative.
* These should be aligned with constants in
* {@link com.android.inputmethod.keyboard.internal.KeyboardCodesSet}.
*/
public static final int CODE_SHIFT = -1;
public static final int CODE_CAPSLOCK = -2;
public static final int CODE_SWITCH_ALPHA_SYMBOL = -3;
public static final int CODE_OUTPUT_TEXT = -4;
public static final int CODE_DELETE = -5;
public static final int CODE_SETTINGS = -6;
public static final int CODE_SHORTCUT = -7;
public static final int CODE_ACTION_NEXT = -8;
public static final int CODE_ACTION_PREVIOUS = -9;
public static final int CODE_LANGUAGE_SWITCH = -10;
public static final int CODE_EMOJI = -11;
public static final int CODE_SHIFT_ENTER = -12;
public static final int CODE_SYMBOL_SHIFT = -13;
public static final int CODE_ALPHA_FROM_EMOJI = -14;
// Code value representing the code is not specified.
public static final int CODE_UNSPECIFIED = -15;
public static boolean isLetterCode(final int code) {
return code >= CODE_SPACE;
}
@Nonnull
public static String printableCode(final int code) {
switch (code) {
case CODE_SHIFT: return "shift";
case CODE_CAPSLOCK: return "capslock";
case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
case CODE_OUTPUT_TEXT: return "text";
case CODE_DELETE: return "delete";
case CODE_SETTINGS: return "settings";
case CODE_SHORTCUT: return "shortcut";
case CODE_ACTION_NEXT: return "actionNext";
case CODE_ACTION_PREVIOUS: return "actionPrevious";
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_SPACE: return "space";
default:
if (code < CODE_SPACE) return String.format("\\u%02X", code);
if (code < 0x100) return String.format("%c", code);
if (code < 0x10000) return String.format("\\u%04X", code);
return String.format("\\U%05X", code);
}
}
@Nonnull
public static String printableCodes(@Nonnull final int[] codes) {
final StringBuilder sb = new StringBuilder();
boolean addDelimiter = false;
for (final int code : codes) {
if (code == NOT_A_CODE) break;
if (addDelimiter) sb.append(", ");
sb.append(printableCode(code));
addDelimiter = true;
}
return "[" + sb + "]";
}
/**
* Screen metrics (a.k.a. Device form factor) constants of
* {@link com.android.inputmethod.latin.R.integer#config_screen_metrics}.
*/
public static final int SCREEN_METRICS_SMALL_PHONE = 0;
public static final int SCREEN_METRICS_LARGE_PHONE = 1;
public static final int SCREEN_METRICS_LARGE_TABLET = 2;
public static final int SCREEN_METRICS_SMALL_TABLET = 3;
@UsedForTesting
public static boolean isPhone(final int screenMetrics) {
return screenMetrics == SCREEN_METRICS_SMALL_PHONE
|| screenMetrics == SCREEN_METRICS_LARGE_PHONE;
}
@UsedForTesting
public static boolean isTablet(final int screenMetrics) {
return screenMetrics == SCREEN_METRICS_SMALL_TABLET
|| screenMetrics == SCREEN_METRICS_LARGE_TABLET;
}
/**
* Default capacity of gesture points container.
* This constant is used by {@link com.android.inputmethod.keyboard.internal.BatchInputArbiter}
* and etc. to preallocate regions that contain gesture event points.
*/
public static final int DEFAULT_GESTURE_POINTS_CAPACITY = 128;
public static final int MAX_IME_DECODER_RESULTS = 20;
public static final int DECODER_SCORE_SCALAR = 1000000;
public static final int DECODER_MAX_SCORE = 1000000000;
public static final int EVENT_BACKSPACE = 1;
public static final int EVENT_REJECTION = 2;
public static final int EVENT_REVERT = 3;
private Constants() {
// This utility class is not publicly instantiable.
}
}

View file

@ -0,0 +1,94 @@
/*
* 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.latin.common;
import javax.annotation.Nonnull;
public final class CoordinateUtils {
private static final int INDEX_X = 0;
private static final int INDEX_Y = 1;
private static final int ELEMENT_SIZE = INDEX_Y + 1;
private CoordinateUtils() {
// This utility class is not publicly instantiable.
}
@Nonnull
public static int[] newInstance() {
return new int[ELEMENT_SIZE];
}
public static int x(@Nonnull final int[] coords) {
return coords[INDEX_X];
}
public static int y(@Nonnull final int[] coords) {
return coords[INDEX_Y];
}
public static void set(@Nonnull final int[] coords, final int x, final int y) {
coords[INDEX_X] = x;
coords[INDEX_Y] = y;
}
public static void copy(@Nonnull final int[] destination, @Nonnull final int[] source) {
destination[INDEX_X] = source[INDEX_X];
destination[INDEX_Y] = source[INDEX_Y];
}
@Nonnull
public static int[] newCoordinateArray(final int arraySize) {
return new int[ELEMENT_SIZE * arraySize];
}
@Nonnull
public static int[] newCoordinateArray(final int arraySize,
final int defaultX, final int defaultY) {
final int[] result = new int[ELEMENT_SIZE * arraySize];
for (int i = 0; i < arraySize; ++i) {
setXYInArray(result, i, defaultX, defaultY);
}
return result;
}
public static int xFromArray(@Nonnull final int[] coordsArray, final int index) {
return coordsArray[ELEMENT_SIZE * index + INDEX_X];
}
public static int yFromArray(@Nonnull final int[] coordsArray, final int index) {
return coordsArray[ELEMENT_SIZE * index + INDEX_Y];
}
@Nonnull
public static int[] coordinateFromArray(@Nonnull final int[] coordsArray, final int index) {
final int[] coords = newInstance();
set(coords, xFromArray(coordsArray, index), yFromArray(coordsArray, index));
return coords;
}
public static void setXYInArray(@Nonnull final int[] coordsArray, final int index,
final int x, final int y) {
final int baseIndex = ELEMENT_SIZE * index;
coordsArray[baseIndex + INDEX_X] = x;
coordsArray[baseIndex + INDEX_Y] = y;
}
public static void setCoordinateInArray(@Nonnull final int[] coordsArray, final int index,
@Nonnull final int[] coords) {
setXYInArray(coordsArray, index, x(coords), y(coords));
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2013 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.latin.common;
import java.io.File;
import java.io.FilenameFilter;
/**
* A simple class to help with removing directories recursively.
*/
public class FileUtils {
private static final String TAG = "FileUtils";
public static boolean deleteRecursively(final File path) {
if (path.isDirectory()) {
final File[] files = path.listFiles();
if (files != null) {
for (final File child : files) {
deleteRecursively(child);
}
}
}
return path.delete();
}
public static boolean deleteFilteredFiles(final File dir, final FilenameFilter fileNameFilter) {
if (!dir.isDirectory()) {
return false;
}
final File[] files = dir.listFiles(fileNameFilter);
if (files == null) {
return false;
}
boolean hasDeletedAllFiles = true;
for (final File file : files) {
if (!deleteRecursively(file)) {
hasDeletedAllFiles = false;
}
}
return hasDeletedAllFiles;
}
public static boolean renameTo(final File fromFile, final File toFile) {
toFile.delete();
return fromFile.renameTo(toFile);
}
}

View file

@ -0,0 +1,166 @@
/*
* 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.latin.common;
import com.android.inputmethod.annotations.UsedForTesting;
import javax.annotation.Nonnull;
// TODO: This class is not thread-safe.
public final class InputPointers {
private static final boolean DEBUG_TIME = false;
private final int mDefaultCapacity;
private final ResizableIntArray mXCoordinates;
private final ResizableIntArray mYCoordinates;
private final ResizableIntArray mPointerIds;
private final ResizableIntArray mTimes;
public InputPointers(final int defaultCapacity) {
mDefaultCapacity = defaultCapacity;
mXCoordinates = new ResizableIntArray(defaultCapacity);
mYCoordinates = new ResizableIntArray(defaultCapacity);
mPointerIds = new ResizableIntArray(defaultCapacity);
mTimes = new ResizableIntArray(defaultCapacity);
}
private void fillWithLastTimeUntil(final int index) {
final int fromIndex = mTimes.getLength();
// Fill the gap with the latest time.
// See {@link #getTime(int)} and {@link #isValidTimeStamps()}.
if (fromIndex <= 0) {
return;
}
final int fillLength = index - fromIndex + 1;
if (fillLength <= 0) {
return;
}
final int lastTime = mTimes.get(fromIndex - 1);
mTimes.fill(lastTime, fromIndex, fillLength);
}
public void addPointerAt(final int index, final int x, final int y, final int pointerId,
final int time) {
mXCoordinates.addAt(index, x);
mYCoordinates.addAt(index, y);
mPointerIds.addAt(index, pointerId);
if (DEBUG_TIME) {
fillWithLastTimeUntil(index);
}
mTimes.addAt(index, time);
}
@UsedForTesting
public void addPointer(final int x, final int y, final int pointerId, final int time) {
mXCoordinates.add(x);
mYCoordinates.add(y);
mPointerIds.add(pointerId);
mTimes.add(time);
}
public void set(@Nonnull final InputPointers ip) {
mXCoordinates.set(ip.mXCoordinates);
mYCoordinates.set(ip.mYCoordinates);
mPointerIds.set(ip.mPointerIds);
mTimes.set(ip.mTimes);
}
public void copy(@Nonnull final InputPointers ip) {
mXCoordinates.copy(ip.mXCoordinates);
mYCoordinates.copy(ip.mYCoordinates);
mPointerIds.copy(ip.mPointerIds);
mTimes.copy(ip.mTimes);
}
/**
* Append the times, x-coordinates and y-coordinates in the specified {@link ResizableIntArray}
* to the end of this.
* @param pointerId the pointer id of the source.
* @param times the source {@link ResizableIntArray} to read the event times from.
* @param xCoordinates the source {@link ResizableIntArray} to read the x-coordinates from.
* @param yCoordinates the source {@link ResizableIntArray} to read the y-coordinates from.
* @param startPos the starting index of the data in {@code times} and etc.
* @param length the number of data to be appended.
*/
public void append(final int pointerId, @Nonnull final ResizableIntArray times,
@Nonnull final ResizableIntArray xCoordinates,
@Nonnull final ResizableIntArray yCoordinates, final int startPos, final int length) {
if (length == 0) {
return;
}
mXCoordinates.append(xCoordinates, startPos, length);
mYCoordinates.append(yCoordinates, startPos, length);
mPointerIds.fill(pointerId, mPointerIds.getLength(), length);
mTimes.append(times, startPos, length);
}
/**
* Shift to the left by elementCount, discarding elementCount pointers at the start.
* @param elementCount how many elements to shift.
*/
@UsedForTesting
public void shift(final int elementCount) {
mXCoordinates.shift(elementCount);
mYCoordinates.shift(elementCount);
mPointerIds.shift(elementCount);
mTimes.shift(elementCount);
}
public void reset() {
final int defaultCapacity = mDefaultCapacity;
mXCoordinates.reset(defaultCapacity);
mYCoordinates.reset(defaultCapacity);
mPointerIds.reset(defaultCapacity);
mTimes.reset(defaultCapacity);
}
public int getPointerSize() {
return mXCoordinates.getLength();
}
@Nonnull
public int[] getXCoordinates() {
return mXCoordinates.getPrimitiveArray();
}
@Nonnull
public int[] getYCoordinates() {
return mYCoordinates.getPrimitiveArray();
}
@Nonnull
public int[] getPointerIds() {
return mPointerIds.getPrimitiveArray();
}
/**
* Gets the time each point was registered, in milliseconds, relative to the first event in the
* sequence.
* @return The time each point was registered, in milliseconds, relative to the first event in
* the sequence.
*/
@Nonnull
public int[] getTimes() {
return mTimes.getPrimitiveArray();
}
@Override
public String toString() {
return "size=" + getPointerSize() + " id=" + mPointerIds + " time=" + mTimes
+ " x=" + mXCoordinates + " y=" + mYCoordinates;
}
}

View file

@ -0,0 +1,210 @@
/*
* Copyright (C) 2011 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.latin.common;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A class to help with handling Locales in string form.
*
* This file has the same meaning and features (and shares all of its code) with the one with the
* same name in Latin IME. They need to be kept synchronized; for any update/bugfix to
* this file, consider also updating/fixing the version in Latin IME.
*/
public final class LocaleUtils {
private LocaleUtils() {
// Intentional empty constructor for utility class.
}
// Locale match level constants.
// A higher level of match is guaranteed to have a higher numerical value.
// Some room is left within constants to add match cases that may arise necessary
// in the future, for example differentiating between the case where the countries
// are both present and different, and the case where one of the locales does not
// specify the countries. This difference is not needed now.
// Nothing matches.
public static final int LOCALE_NO_MATCH = 0;
// The languages matches, but the country are different. Or, the reference locale requires a
// country and the tested locale does not have one.
public static final int LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER = 3;
// The languages and country match, but the variants are different. Or, the reference locale
// requires a variant and the tested locale does not have one.
public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER = 6;
// The required locale is null or empty so it will accept anything, and the tested locale
// is non-null and non-empty.
public static final int LOCALE_ANY_MATCH = 10;
// The language matches, and the tested locale specifies a country but the reference locale
// does not require one.
public static final int LOCALE_LANGUAGE_MATCH = 15;
// The language and the country match, and the tested locale specifies a variant but the
// reference locale does not require one.
public static final int LOCALE_LANGUAGE_AND_COUNTRY_MATCH = 20;
// The compared locales are fully identical. This is the best match level.
public static final int LOCALE_FULL_MATCH = 30;
// The level at which a match is "normally" considered a locale match with standard algorithms.
// Don't use this directly, use #isMatch to test.
private static final int LOCALE_MATCH = LOCALE_ANY_MATCH;
// Make this match the maximum match level. If this evolves to have more than 2 digits
// when written in base 10, also adjust the getMatchLevelSortedString method.
private static final int MATCH_LEVEL_MAX = 30;
/**
* Return how well a tested locale matches a reference locale.
*
* This will check the tested locale against the reference locale and return a measure of how
* a well it matches the reference. The general idea is that the tested locale has to match
* every specified part of the required locale. A full match occur when they are equal, a
* partial match when the tested locale agrees with the reference locale but is more specific,
* and a difference when the tested locale does not comply with all requirements from the
* reference locale.
* In more detail, if the reference locale specifies at least a language and the testedLocale
* does not specify one, or specifies a different one, LOCALE_NO_MATCH is returned. If the
* reference locale is empty or null, it will match anything - in the form of LOCALE_FULL_MATCH
* if the tested locale is empty or null, and LOCALE_ANY_MATCH otherwise. If the reference and
* tested locale agree on the language, but not on the country,
* LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER is returned if the reference locale specifies a country,
* and LOCALE_LANGUAGE_MATCH otherwise.
* If they agree on both the language and the country, but not on the variant,
* LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER is returned if the reference locale
* specifies a variant, and LOCALE_LANGUAGE_AND_COUNTRY_MATCH otherwise. If everything matches,
* LOCALE_FULL_MATCH is returned.
* Examples:
* en <=> en_US => LOCALE_LANGUAGE_MATCH
* en_US <=> en => LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
* en_US_POSIX <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER
* en_US <=> en_US_Android => LOCALE_LANGUAGE_AND_COUNTRY_MATCH
* sp_US <=> en_US => LOCALE_NO_MATCH
* de <=> de => LOCALE_FULL_MATCH
* en_US <=> en_US => LOCALE_FULL_MATCH
* "" <=> en_US => LOCALE_ANY_MATCH
*
* @param referenceLocale the reference locale to test against.
* @param testedLocale the locale to test.
* @return a constant that measures how well the tested locale matches the reference locale.
*/
public static int getMatchLevel(@Nullable final String referenceLocale,
@Nullable final String testedLocale) {
if (StringUtils.isEmpty(referenceLocale)) {
return StringUtils.isEmpty(testedLocale) ? LOCALE_FULL_MATCH : LOCALE_ANY_MATCH;
}
if (null == testedLocale) return LOCALE_NO_MATCH;
final String[] referenceParams = referenceLocale.split("_", 3);
final String[] testedParams = testedLocale.split("_", 3);
// By spec of String#split, [0] cannot be null and length cannot be 0.
if (!referenceParams[0].equals(testedParams[0])) return LOCALE_NO_MATCH;
switch (referenceParams.length) {
case 1:
return 1 == testedParams.length ? LOCALE_FULL_MATCH : LOCALE_LANGUAGE_MATCH;
case 2:
if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
if (!referenceParams[1].equals(testedParams[1]))
return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
if (3 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH;
return LOCALE_FULL_MATCH;
case 3:
if (1 == testedParams.length) return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
if (!referenceParams[1].equals(testedParams[1]))
return LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
if (2 == testedParams.length) return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
if (!referenceParams[2].equals(testedParams[2]))
return LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER;
return LOCALE_FULL_MATCH;
}
// It should be impossible to come here
return LOCALE_NO_MATCH;
}
/**
* Return a string that represents this match level, with better matches first.
*
* The strings are sorted in lexicographic order: a better match will always be less than
* a worse match when compared together.
*/
public static String getMatchLevelSortedString(final int matchLevel) {
// This works because the match levels are 0~99 (actually 0~30)
// Ideally this should use a number of digits equals to the 1og10 of the greater matchLevel
return String.format(Locale.ROOT, "%02d", MATCH_LEVEL_MAX - matchLevel);
}
/**
* Find out whether a match level should be considered a match.
*
* This method takes a match level as returned by the #getMatchLevel method, and returns whether
* it should be considered a match in the usual sense with standard Locale functions.
*
* @param level the match level, as returned by getMatchLevel.
* @return whether this is a match or not.
*/
public static boolean isMatch(final int level) {
return LOCALE_MATCH <= level;
}
private static final HashMap<String, Locale> sLocaleCache = new HashMap<>();
/**
* Creates a locale from a string specification.
* @param localeString a string specification of a locale, in a format of "ll_cc_variant" where
* "ll" is a language code, "cc" is a country code.
*/
@Nonnull
public static Locale constructLocaleFromString(@Nonnull final String localeString) {
synchronized (sLocaleCache) {
if (sLocaleCache.containsKey(localeString)) {
return sLocaleCache.get(localeString);
}
final String[] elements = localeString.split("_", 3);
final Locale locale;
if (elements.length == 1) {
locale = new Locale(elements[0] /* language */);
} else if (elements.length == 2) {
locale = new Locale(elements[0] /* language */, elements[1] /* country */);
} else { // localeParams.length == 3
locale = new Locale(elements[0] /* language */, elements[1] /* country */,
elements[2] /* variant */);
}
sLocaleCache.put(localeString, locale);
return locale;
}
}
// TODO: Get this information from the framework instead of maintaining here by ourselves.
private static final HashSet<String> sRtlLanguageCodes = new HashSet<>();
static {
// List of known Right-To-Left language codes.
sRtlLanguageCodes.add("ar"); // Arabic
sRtlLanguageCodes.add("fa"); // Persian
sRtlLanguageCodes.add("iw"); // Hebrew
sRtlLanguageCodes.add("ku"); // Kurdish
sRtlLanguageCodes.add("ps"); // Pashto
sRtlLanguageCodes.add("sd"); // Sindhi
sRtlLanguageCodes.add("ug"); // Uyghur
sRtlLanguageCodes.add("ur"); // Urdu
sRtlLanguageCodes.add("yi"); // Yiddish
}
public static boolean isRtlLanguage(@Nonnull final Locale locale) {
return sRtlLanguageCodes.contains(locale.getLanguage());
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 2013 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.latin.common;
public class NativeSuggestOptions {
// Need to update suggest_options.h when you add, remove or reorder options.
private static final int IS_GESTURE = 0;
private static final int USE_FULL_EDIT_DISTANCE = 1;
private static final int BLOCK_OFFENSIVE_WORDS = 2;
private static final int SPACE_AWARE_GESTURE_ENABLED = 3;
private static final int WEIGHT_FOR_LOCALE_IN_THOUSANDS = 4;
private static final int OPTIONS_SIZE = 5;
private final int[] mOptions;
public NativeSuggestOptions() {
mOptions = new int[OPTIONS_SIZE];
}
public void setIsGesture(final boolean value) {
setBooleanOption(IS_GESTURE, value);
}
public void setUseFullEditDistance(final boolean value) {
setBooleanOption(USE_FULL_EDIT_DISTANCE, value);
}
public void setBlockOffensiveWords(final boolean value) {
setBooleanOption(BLOCK_OFFENSIVE_WORDS, value);
}
public void setWeightForLocale(final float value) {
// We're passing this option as a fixed point value, in thousands. This is decoded in
// native code by SuggestOptions#weightForLocale().
setIntegerOption(WEIGHT_FOR_LOCALE_IN_THOUSANDS, (int) (value * 1000));
}
public int[] getOptions() {
return mOptions;
}
private void setBooleanOption(final int key, final boolean value) {
mOptions[key] = value ? 1 : 0;
}
private void setIntegerOption(final int key, final int value) {
mOptions[key] = value;
}
}

View file

@ -0,0 +1,162 @@
/*
* 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.latin.common;
import com.android.inputmethod.annotations.UsedForTesting;
import java.util.Arrays;
import javax.annotation.Nonnull;
// TODO: This class is not thread-safe.
public final class ResizableIntArray {
@Nonnull
private int[] mArray;
private int mLength;
public ResizableIntArray(final int capacity) {
reset(capacity);
}
public int get(final int index) {
if (index < mLength) {
return mArray[index];
}
throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index);
}
public void addAt(final int index, final int val) {
if (index < mLength) {
mArray[index] = val;
} else {
mLength = index;
add(val);
}
}
public void add(final int val) {
final int currentLength = mLength;
ensureCapacity(currentLength + 1);
mArray[currentLength] = val;
mLength = currentLength + 1;
}
/**
* Calculate the new capacity of {@code mArray}.
* @param minimumCapacity the minimum capacity that the {@code mArray} should have.
* @return the new capacity that the {@code mArray} should have. Returns zero when there is no
* need to expand {@code mArray}.
*/
private int calculateCapacity(final int minimumCapacity) {
final int currentCapcity = mArray.length;
if (currentCapcity < minimumCapacity) {
final int nextCapacity = currentCapcity * 2;
// The following is the same as return Math.max(minimumCapacity, nextCapacity);
return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity;
}
return 0;
}
private void ensureCapacity(final int minimumCapacity) {
final int newCapacity = calculateCapacity(minimumCapacity);
if (newCapacity > 0) {
// TODO: Implement primitive array pool.
mArray = Arrays.copyOf(mArray, newCapacity);
}
}
public int getLength() {
return mLength;
}
public void setLength(final int newLength) {
ensureCapacity(newLength);
mLength = newLength;
}
public void reset(final int capacity) {
// TODO: Implement primitive array pool.
mArray = new int[capacity];
mLength = 0;
}
@Nonnull
public int[] getPrimitiveArray() {
return mArray;
}
public void set(@Nonnull final ResizableIntArray ip) {
// TODO: Implement primitive array pool.
mArray = ip.mArray;
mLength = ip.mLength;
}
public void copy(@Nonnull final ResizableIntArray ip) {
final int newCapacity = calculateCapacity(ip.mLength);
if (newCapacity > 0) {
// TODO: Implement primitive array pool.
mArray = new int[newCapacity];
}
System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength);
mLength = ip.mLength;
}
public void append(@Nonnull final ResizableIntArray src, final int startPos, final int length) {
if (length == 0) {
return;
}
final int currentLength = mLength;
final int newLength = currentLength + length;
ensureCapacity(newLength);
System.arraycopy(src.mArray, startPos, mArray, currentLength, length);
mLength = newLength;
}
public void fill(final int value, final int startPos, final int length) {
if (startPos < 0 || length < 0) {
throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length);
}
final int endPos = startPos + length;
ensureCapacity(endPos);
Arrays.fill(mArray, startPos, endPos, value);
if (mLength < endPos) {
mLength = endPos;
}
}
/**
* Shift to the left by elementCount, discarding elementCount pointers at the start.
* @param elementCount how many elements to shift.
*/
@UsedForTesting
public void shift(final int elementCount) {
System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount);
mLength -= elementCount;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < mLength; i++) {
if (i != 0) {
sb.append(",");
}
sb.append(mArray[i]);
}
return "[" + sb + "]";
}
}

View file

@ -0,0 +1,704 @@
/*
* 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.latin.common;
import com.android.inputmethod.annotations.UsedForTesting;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class StringUtils {
public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
public static final int CAPITALIZE_FIRST = 1; // First only
public static final int CAPITALIZE_ALL = 2; // All caps
@Nonnull
private static final String EMPTY_STRING = "";
private static final char CHAR_LINE_FEED = 0X000A;
private static final char CHAR_VERTICAL_TAB = 0X000B;
private static final char CHAR_FORM_FEED = 0X000C;
private static final char CHAR_CARRIAGE_RETURN = 0X000D;
private static final char CHAR_NEXT_LINE = 0X0085;
private static final char CHAR_LINE_SEPARATOR = 0X2028;
private static final char CHAR_PARAGRAPH_SEPARATOR = 0X2029;
private StringUtils() {
// This utility class is not publicly instantiable.
}
// Taken from android.text.TextUtils. We are extensively using this method in many places,
// some of which don't have the android libraries available.
/**
* Returns true if the string is null or 0-length.
* @param str the string to be examined
* @return true if str is null or zero length
*/
public static boolean isEmpty(@Nullable final CharSequence str) {
return (str == null || str.length() == 0);
}
// Taken from android.text.TextUtils to cut the dependency to the Android framework.
/**
* Returns a string containing the tokens joined by delimiters.
* @param delimiter the delimiter
* @param tokens an array objects to be joined. Strings will be formed from
* the objects by calling object.toString().
*/
@Nonnull
public static String join(@Nonnull final CharSequence delimiter,
@Nonnull final Iterable<?> tokens) {
final StringBuilder sb = new StringBuilder();
boolean firstTime = true;
for (final Object token: tokens) {
if (firstTime) {
firstTime = false;
} else {
sb.append(delimiter);
}
sb.append(token);
}
return sb.toString();
}
// Taken from android.text.TextUtils to cut the dependency to the Android framework.
/**
* Returns true if a and b are equal, including if they are both null.
* <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
* both the arguments were instances of String.</i></p>
* @param a first CharSequence to check
* @param b second CharSequence to check
* @return true if a and b are equal
*/
public static boolean equals(@Nullable final CharSequence a, @Nullable final CharSequence b) {
if (a == b) {
return true;
}
final int length;
if (a != null && b != null && (length = a.length()) == b.length()) {
if (a instanceof String && b instanceof String) {
return a.equals(b);
}
for (int i = 0; i < length; i++) {
if (a.charAt(i) != b.charAt(i)) {
return false;
}
}
return true;
}
return false;
}
public static int codePointCount(@Nullable final CharSequence text) {
if (isEmpty(text)) {
return 0;
}
return Character.codePointCount(text, 0, text.length());
}
@Nonnull
public static String newSingleCodePointString(final int codePoint) {
if (Character.charCount(codePoint) == 1) {
// Optimization: avoid creating a temporary array for characters that are
// represented by a single char value
return String.valueOf((char) codePoint);
}
// For surrogate pair
return new String(Character.toChars(codePoint));
}
public static boolean containsInArray(@Nonnull final String text,
@Nonnull final String[] array) {
for (final String element : array) {
if (text.equals(element)) {
return true;
}
}
return false;
}
/**
* Comma-Splittable Text is similar to Comma-Separated Values (CSV) but has much simpler syntax.
* Unlike CSV, Comma-Splittable Text has no escaping mechanism, so that the text can't contain
* a comma character in it.
*/
@Nonnull
private static final String SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT = ",";
public static boolean containsInCommaSplittableText(@Nonnull final String text,
@Nullable final String extraValues) {
if (isEmpty(extraValues)) {
return false;
}
return containsInArray(text, extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT));
}
@Nonnull
public static String removeFromCommaSplittableTextIfExists(@Nonnull final String text,
@Nullable final String extraValues) {
if (isEmpty(extraValues)) {
return EMPTY_STRING;
}
final String[] elements = extraValues.split(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT);
if (!containsInArray(text, elements)) {
return extraValues;
}
final ArrayList<String> result = new ArrayList<>(elements.length - 1);
for (final String element : elements) {
if (!text.equals(element)) {
result.add(element);
}
}
return join(SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT, result);
}
/**
* Remove duplicates from an array of strings.
*
* This method will always keep the first occurrence of all strings at their position
* in the array, removing the subsequent ones.
*/
public static void removeDupes(@Nonnull final ArrayList<String> suggestions) {
if (suggestions.size() < 2) {
return;
}
int i = 1;
// Don't cache suggestions.size(), since we may be removing items
while (i < suggestions.size()) {
final String cur = suggestions.get(i);
// Compare each suggestion with each previous suggestion
for (int j = 0; j < i; j++) {
final String previous = suggestions.get(j);
if (equals(cur, previous)) {
suggestions.remove(i);
i--;
break;
}
}
i++;
}
}
@Nonnull
public static String capitalizeFirstCodePoint(@Nonnull final String s,
@Nonnull final Locale locale) {
if (s.length() <= 1) {
return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
}
// Please refer to the comment below in
// {@link #capitalizeFirstAndDowncaseRest(String,Locale)} as this has the same shortcomings
final int cutoff = s.offsetByCodePoints(0, 1);
return s.substring(0, cutoff).toUpperCase(getLocaleUsedForToTitleCase(locale))
+ s.substring(cutoff);
}
@Nonnull
public static String capitalizeFirstAndDowncaseRest(@Nonnull final String s,
@Nonnull final Locale locale) {
if (s.length() <= 1) {
return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
}
// TODO: fix the bugs below
// - It does not work for Serbian, because it fails to account for the "lj" character,
// which should be "Lj" in title case and "LJ" in upper case.
// - It does not work for Dutch, because it fails to account for the "ij" digraph when it's
// written as two separate code points. They are two different characters but both should
// be capitalized as "IJ" as if they were a single letter in most words (not all). If the
// unicode char for the ligature is used however, it works.
final int cutoff = s.offsetByCodePoints(0, 1);
return s.substring(0, cutoff).toUpperCase(getLocaleUsedForToTitleCase(locale))
+ s.substring(cutoff).toLowerCase(locale);
}
@Nonnull
public static int[] toCodePointArray(@Nonnull final CharSequence charSequence) {
return toCodePointArray(charSequence, 0, charSequence.length());
}
@Nonnull
private static final int[] EMPTY_CODEPOINTS = {};
/**
* Converts a range of a string to an array of code points.
* @param charSequence the source string.
* @param startIndex the start index inside the string in java chars, inclusive.
* @param endIndex the end index inside the string in java chars, exclusive.
* @return a new array of code points. At most endIndex - startIndex, but possibly less.
*/
@Nonnull
public static int[] toCodePointArray(@Nonnull final CharSequence charSequence,
final int startIndex, final int endIndex) {
final int length = charSequence.length();
if (length <= 0) {
return EMPTY_CODEPOINTS;
}
final int[] codePoints =
new int[Character.codePointCount(charSequence, startIndex, endIndex)];
copyCodePointsAndReturnCodePointCount(codePoints, charSequence, startIndex, endIndex,
false /* downCase */);
return codePoints;
}
/**
* Copies the codepoints in a CharSequence to an int array.
*
* This method assumes there is enough space in the array to store the code points. The size
* can be measured with Character#codePointCount(CharSequence, int, int) before passing to this
* method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown.
* Also, this method makes no effort to be thread-safe. Do not modify the CharSequence while
* this method is running, or the behavior is undefined.
* This method can optionally downcase code points before copying them, but it pays no attention
* to locale while doing so.
*
* @param destination the int array.
* @param charSequence the CharSequence.
* @param startIndex the start index inside the string in java chars, inclusive.
* @param endIndex the end index inside the string in java chars, exclusive.
* @param downCase if this is true, code points will be downcased before being copied.
* @return the number of copied code points.
*/
public static int copyCodePointsAndReturnCodePointCount(@Nonnull final int[] destination,
@Nonnull final CharSequence charSequence, final int startIndex, final int endIndex,
final boolean downCase) {
int destIndex = 0;
for (int index = startIndex; index < endIndex;
index = Character.offsetByCodePoints(charSequence, index, 1)) {
final int codePoint = Character.codePointAt(charSequence, index);
// TODO: stop using this, as it's not aware of the locale and does not always do
// the right thing.
destination[destIndex] = downCase ? Character.toLowerCase(codePoint) : codePoint;
destIndex++;
}
return destIndex;
}
@Nonnull
public static int[] toSortedCodePointArray(@Nonnull final String string) {
final int[] codePoints = toCodePointArray(string);
Arrays.sort(codePoints);
return codePoints;
}
/**
* Construct a String from a code point array
*
* @param codePoints a code point array that is null terminated when its logical length is
* shorter than the array length.
* @return a string constructed from the code point array.
*/
@Nonnull
public static String getStringFromNullTerminatedCodePointArray(
@Nonnull final int[] codePoints) {
int stringLength = codePoints.length;
for (int i = 0; i < codePoints.length; i++) {
if (codePoints[i] == 0) {
stringLength = i;
break;
}
}
return new String(codePoints, 0 /* offset */, stringLength);
}
// This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE.
public static int getCapitalizationType(@Nonnull final String text) {
// If the first char is not uppercase, then the word is either all lower case or
// camel case, and in either case we return CAPITALIZE_NONE.
final int len = text.length();
int index = 0;
for (; index < len; index = text.offsetByCodePoints(index, 1)) {
if (Character.isLetter(text.codePointAt(index))) {
break;
}
}
if (index == len) return CAPITALIZE_NONE;
if (!Character.isUpperCase(text.codePointAt(index))) {
return CAPITALIZE_NONE;
}
int capsCount = 1;
int letterCount = 1;
for (index = text.offsetByCodePoints(index, 1); index < len;
index = text.offsetByCodePoints(index, 1)) {
if (1 != capsCount && letterCount != capsCount) break;
final int codePoint = text.codePointAt(index);
if (Character.isUpperCase(codePoint)) {
++capsCount;
++letterCount;
} else if (Character.isLetter(codePoint)) {
// We need to discount non-letters since they may not be upper-case, but may
// still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
++letterCount;
}
}
// We know the first char is upper case. So we want to test if either every letter other
// than the first is lower case, or if they are all upper case. If the string is exactly
// one char long, then we will arrive here with letterCount 1, and this is correct, too.
if (1 == capsCount) return CAPITALIZE_FIRST;
return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
}
public static boolean isIdenticalAfterUpcase(@Nonnull final String text) {
final int length = text.length();
int i = 0;
while (i < length) {
final int codePoint = text.codePointAt(i);
if (Character.isLetter(codePoint) && !Character.isUpperCase(codePoint)) {
return false;
}
i += Character.charCount(codePoint);
}
return true;
}
public static boolean isIdenticalAfterDowncase(@Nonnull final String text) {
final int length = text.length();
int i = 0;
while (i < length) {
final int codePoint = text.codePointAt(i);
if (Character.isLetter(codePoint) && !Character.isLowerCase(codePoint)) {
return false;
}
i += Character.charCount(codePoint);
}
return true;
}
public static boolean isIdenticalAfterCapitalizeEachWord(@Nonnull final String text,
@Nonnull final int[] sortedSeparators) {
boolean needsCapsNext = true;
final int len = text.length();
for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
final int codePoint = text.codePointAt(i);
if (Character.isLetter(codePoint)) {
if ((needsCapsNext && !Character.isUpperCase(codePoint))
|| (!needsCapsNext && !Character.isLowerCase(codePoint))) {
return false;
}
}
// We need a capital letter next if this is a separator.
needsCapsNext = (Arrays.binarySearch(sortedSeparators, codePoint) >= 0);
}
return true;
}
// TODO: like capitalizeFirst*, this does not work perfectly for Dutch because of the IJ digraph
// which should be capitalized together in *some* cases.
@Nonnull
public static String capitalizeEachWord(@Nonnull final String text,
@Nonnull final int[] sortedSeparators, @Nonnull final Locale locale) {
final StringBuilder builder = new StringBuilder();
boolean needsCapsNext = true;
final int len = text.length();
for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
final String nextChar = text.substring(i, text.offsetByCodePoints(i, 1));
if (needsCapsNext) {
builder.append(nextChar.toUpperCase(locale));
} else {
builder.append(nextChar.toLowerCase(locale));
}
// We need a capital letter next if this is a separator.
needsCapsNext = (Arrays.binarySearch(sortedSeparators, nextChar.codePointAt(0)) >= 0);
}
return builder.toString();
}
/**
* Approximates whether the text before the cursor looks like a URL.
*
* This is not foolproof, but it should work well in the practice.
* Essentially it walks backward from the cursor until it finds something that's not a letter,
* digit, or common URL symbol like underscore. If it hasn't found a period yet, then it
* does not look like a URL.
* If the text:
* - starts with www and contains a period
* - starts with a slash preceded by either a slash, whitespace, or start-of-string
* Then it looks like a URL and we return true. Otherwise, we return false.
*
* Note: this method is called quite often, and should be fast.
*
* TODO: This will return that "abc./def" and ".abc/def" look like URLs to keep down the
* code complexity, but ideally it should not. It's acceptable for now.
*/
public static boolean lastPartLooksLikeURL(@Nonnull final CharSequence text) {
int i = text.length();
if (0 == i) {
return false;
}
int wCount = 0;
int slashCount = 0;
boolean hasSlash = false;
boolean hasPeriod = false;
int codePoint = 0;
while (i > 0) {
codePoint = Character.codePointBefore(text, i);
if (codePoint < Constants.CODE_PERIOD || codePoint > 'z') {
// Handwavy heuristic to see if that's a URL character. Anything between period
// and z. This includes all lower- and upper-case ascii letters, period,
// underscore, arrobase, question mark, equal sign. It excludes spaces, exclamation
// marks, double quotes...
// Anything that's not a URL-like character causes us to break from here and
// evaluate normally.
break;
}
if (Constants.CODE_PERIOD == codePoint) {
hasPeriod = true;
}
if (Constants.CODE_SLASH == codePoint) {
hasSlash = true;
if (2 == ++slashCount) {
return true;
}
} else {
slashCount = 0;
}
if ('w' == codePoint) {
++wCount;
} else {
wCount = 0;
}
i = Character.offsetByCodePoints(text, i, -1);
}
// End of the text run.
// If it starts with www and includes a period, then it looks like a URL.
if (wCount >= 3 && hasPeriod) {
return true;
}
// If it starts with a slash, and the code point before is whitespace, it looks like an URL.
if (1 == slashCount && (0 == i || Character.isWhitespace(codePoint))) {
return true;
}
// If it has both a period and a slash, it looks like an URL.
if (hasPeriod && hasSlash) {
return true;
}
// Otherwise, it doesn't look like an URL.
return false;
}
/**
* Examines the string and returns whether we're inside a double quote.
*
* This is used to decide whether we should put an automatic space before or after a double
* quote character. If we're inside a quotation, then we want to close it, so we want a space
* after and not before. Otherwise, we want to open the quotation, so we want a space before
* and not after. Exception: after a digit, we never want a space because the "inch" or
* "minutes" use cases is dominant after digits.
* In the practice, we determine whether we are in a quotation or not by finding the previous
* double quote character, and looking at whether it's followed by whitespace. If so, that
* was a closing quotation mark, so we're not inside a double quote. If it's not followed
* by whitespace, then it was an opening quotation mark, and we're inside a quotation.
*
* @param text the text to examine.
* @return whether we're inside a double quote.
*/
public static boolean isInsideDoubleQuoteOrAfterDigit(@Nonnull final CharSequence text) {
int i = text.length();
if (0 == i) {
return false;
}
int codePoint = Character.codePointBefore(text, i);
if (Character.isDigit(codePoint)) {
return true;
}
int prevCodePoint = 0;
while (i > 0) {
codePoint = Character.codePointBefore(text, i);
if (Constants.CODE_DOUBLE_QUOTE == codePoint) {
// If we see a double quote followed by whitespace, then that
// was a closing quote.
if (Character.isWhitespace(prevCodePoint)) {
return false;
}
}
if (Character.isWhitespace(codePoint) && Constants.CODE_DOUBLE_QUOTE == prevCodePoint) {
// If we see a double quote preceded by whitespace, then that
// was an opening quote. No need to continue seeking.
return true;
}
i -= Character.charCount(codePoint);
prevCodePoint = codePoint;
}
// We reached the start of text. If the first char is a double quote, then we're inside
// a double quote. Otherwise we're not.
return Constants.CODE_DOUBLE_QUOTE == codePoint;
}
public static boolean isEmptyStringOrWhiteSpaces(@Nonnull final String s) {
final int N = codePointCount(s);
for (int i = 0; i < N; ++i) {
if (!Character.isWhitespace(s.codePointAt(i))) {
return false;
}
}
return true;
}
@UsedForTesting
@Nonnull
public static String byteArrayToHexString(@Nullable final byte[] bytes) {
if (bytes == null || bytes.length == 0) {
return EMPTY_STRING;
}
final StringBuilder sb = new StringBuilder();
for (final byte b : bytes) {
sb.append(String.format("%02x", b & 0xff));
}
return sb.toString();
}
/**
* Convert hex string to byte array. The string length must be an even number.
*/
@UsedForTesting
@Nullable
public static byte[] hexStringToByteArray(@Nullable final String hexString) {
if (isEmpty(hexString)) {
return null;
}
final int N = hexString.length();
if (N % 2 != 0) {
throw new NumberFormatException("Input hex string length must be an even number."
+ " Length = " + N);
}
final byte[] bytes = new byte[N / 2];
for (int i = 0; i < N; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return bytes;
}
private static final String LANGUAGE_GREEK = "el";
@Nonnull
private static Locale getLocaleUsedForToTitleCase(@Nonnull final Locale locale) {
// In Greek locale {@link String#toUpperCase(Locale)} eliminates accents from its result.
// In order to get accented upper case letter, {@link Locale#ROOT} should be used.
if (LANGUAGE_GREEK.equals(locale.getLanguage())) {
return Locale.ROOT;
}
return locale;
}
@Nullable
public static String toTitleCaseOfKeyLabel(@Nullable final String label,
@Nonnull final Locale locale) {
if (label == null) {
return label;
}
return label.toUpperCase(getLocaleUsedForToTitleCase(locale));
}
public static int toTitleCaseOfKeyCode(final int code, @Nonnull final Locale locale) {
if (!Constants.isLetterCode(code)) {
return code;
}
final String label = newSingleCodePointString(code);
final String titleCaseLabel = toTitleCaseOfKeyLabel(label, locale);
return codePointCount(titleCaseLabel) == 1
? titleCaseLabel.codePointAt(0) : Constants.CODE_UNSPECIFIED;
}
public static int getTrailingSingleQuotesCount(@Nonnull final CharSequence charSequence) {
final int lastIndex = charSequence.length() - 1;
int i = lastIndex;
while (i >= 0 && charSequence.charAt(i) == Constants.CODE_SINGLE_QUOTE) {
--i;
}
return lastIndex - i;
}
@UsedForTesting
public static class Stringizer<E> {
@Nonnull
private static final String[] EMPTY_STRING_ARRAY = new String[0];
@UsedForTesting
@Nonnull
public String stringize(@Nullable final E element) {
if (element == null) {
return "null";
}
return element.toString();
}
@UsedForTesting
@Nonnull
public final String join(@Nullable final E[] array) {
return joinStringArray(toStringArray(array), null /* delimiter */);
}
@UsedForTesting
public final String join(@Nullable final E[] array, @Nullable final String delimiter) {
return joinStringArray(toStringArray(array), delimiter);
}
@Nonnull
protected String[] toStringArray(@Nullable final E[] array) {
if (array == null) {
return EMPTY_STRING_ARRAY;
}
final String[] stringArray = new String[array.length];
for (int index = 0; index < array.length; index++) {
stringArray[index] = stringize(array[index]);
}
return stringArray;
}
@Nonnull
protected String joinStringArray(@Nonnull final String[] stringArray,
@Nullable final String delimiter) {
if (delimiter == null) {
return Arrays.toString(stringArray);
}
final StringBuilder sb = new StringBuilder();
for (int index = 0; index < stringArray.length; index++) {
sb.append(index == 0 ? "[" : delimiter);
sb.append(stringArray[index]);
}
return sb + "]";
}
}
/**
* Returns whether the last composed word contains line-breaking character (e.g. CR or LF).
* @param text the text to be examined.
* @return {@code true} if the last composed word contains line-breaking separator.
*/
public static boolean hasLineBreakCharacter(@Nullable final String text) {
if (isEmpty(text)) {
return false;
}
for (int i = text.length() - 1; i >= 0; --i) {
final char c = text.charAt(i);
switch (c) {
case CHAR_LINE_FEED:
case CHAR_VERTICAL_TAB:
case CHAR_FORM_FEED:
case CHAR_CARRIAGE_RETURN:
case CHAR_NEXT_LINE:
case CHAR_LINE_SEPARATOR:
case CHAR_PARAGRAPH_SEPARATOR:
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2015 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.latin.common;
/**
* Emojis are supplementary characters expressed as a low+high pair. For instance,
* the emoji U+1F625 is encoded as "\uD83D\uDE25" in UTF-16, where '\uD83D' is in
* the range of [0xd800, 0xdbff] and '\uDE25' is in the range of [0xdc00, 0xdfff].
* {@see http://docs.oracle.com/javase/6/docs/api/java/lang/Character.html#unicode}
*/
public final class UnicodeSurrogate {
private static final char LOW_SURROGATE_MIN = '\uD800';
private static final char LOW_SURROGATE_MAX = '\uDBFF';
private static final char HIGH_SURROGATE_MIN = '\uDC00';
private static final char HIGH_SURROGATE_MAX = '\uDFFF';
public static boolean isLowSurrogate(final char c) {
return c >= LOW_SURROGATE_MIN && c <= LOW_SURROGATE_MAX;
}
public static boolean isHighSurrogate(final char c) {
return c >= HIGH_SURROGATE_MIN && c <= HIGH_SURROGATE_MAX;
}
}

View file

@ -0,0 +1,38 @@
# This is a sample wordlist that can be converted to a binary dictionary
# for use by the Latin IME.
# The file is essentially a CSV file, with indent level denoting nesting.
#
# The file starts with a single CSV line with the header attributes. Whatever
# the content, these are included as is in the binary file. The first attribute
# of the file should be `dictionary'. Usual fields are `locale', `description',
# `date', `version', `options'.
#
# Each word has a `word' entry and at least a `f' argument denoting its
# probability, as an integer between 0 and 255 on a logarithmic scale, with
# 255 meaning 1 and each decrement in 1 dividing probability by 1.15.
# As a special case, a weight of 0 is taken to mean profanity - words that
# should not be considered a typo, but that should never be suggested
# explicitly. An entry may be made not a word by adding a `not_a_word'
# field with a value of `true'. The main reason for putting such entries
# into the dictionary is to add shortcut targets and maybe a whitelist
# replacement.
#
# Each word may or may not have any number of shortcut target lines
# starting with a `shortcut' entry and having at least a `f' frequency
# value between 0 and 14, or the special value `whitelist' which becomes
# 15, which is then taken to be the whitelist target of this word.
#
# Each word may also have any number of bigram lines starting with a
# `bigram' entry containing the following word whose frequency should
# override the unigram frequency when following the word this bigram is
# for.
#
dictionary=main:en,locale=en,description=Sample wordlist,date=1351495318,version=1
word=sample,f=200
bigram=wordlist,f=243
word=wordlist,f=180
word=shortcut,f=176
shortcut=target,f=10
word=witelisted,f=10,not_a_word=true
shortcut=whitelisted,f=whitelist
word=profanity,f=0

View file

@ -0,0 +1,30 @@
/*
* Copyright (C) 2013 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.compat;
import android.content.pm.PackageInfo;
@SuppressWarnings("unused")
public class AppWorkaroundsHelper {
private AppWorkaroundsHelper() {
// This helper class is not publicly instantiable.
}
public static boolean evaluateIsBrokenByRecorrection(final PackageInfo info) {
return false;
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (C) 2013 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.dictionarypack;
/**
* A class to group constants for dictionary pack usage.
*
* This class only defines constants. It should not make any references to outside code as far as
* possible, as it's used to separate cleanly the keyboard code from the dictionary pack code; this
* is needed in particular to cleanly compile regression tests.
*/
public class DictionaryPackConstants {
/**
* The root domain for the dictionary pack, upon which authorities and actions will append
* their own distinctive strings.
*/
private static final String DICTIONARY_DOMAIN = "com.android.inputmethod.dictionarypack.aosp";
/**
* Authority for the ContentProvider protocol.
*/
// TODO: find some way to factorize this string with the one in the resources
public static final String AUTHORITY = DICTIONARY_DOMAIN;
/**
* The action of the intent for publishing that new dictionary data is available.
*/
// TODO: make this different across different packages. A suggested course of action is
// to use the package name inside this string.
// NOTE: The appended string should be uppercase like all other actions, but it's not for
// historical reasons.
public static final String NEW_DICTIONARY_INTENT_ACTION = DICTIONARY_DOMAIN + ".newdict";
/**
* The action of the intent sent by the dictionary pack to ask for a client to make
* itself known. This is used when the settings activity is brought up for a client the
* dictionary pack does not know about.
*/
public static final String UNKNOWN_DICTIONARY_PROVIDER_CLIENT = DICTIONARY_DOMAIN
+ ".UNKNOWN_CLIENT";
// In the above intents, the name of the string extra that contains the name of the client
// we want information about.
public static final String DICTIONARY_PROVIDER_CLIENT_EXTRA = "client";
/**
* The action of the intent to tell the dictionary provider to update now.
*/
public static final String UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN
+ ".UPDATE_NOW";
/**
* The intent action to inform the dictionary provider to initialize the db
* and update now.
*/
public static final String INIT_AND_UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN
+ ".INIT_AND_UPDATE_NOW";
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (C) 2013 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.dictionarypack;
import android.content.Context;
/**
* Helper to get the metadata URI from its base URI.
*/
@SuppressWarnings("unused")
public class MetadataUriGetter {
public static String getUri(final Context context, final String baseUri) {
return baseUri;
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (C) 2013 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.latin;
/**
* Factory for instantiating DictionaryFacilitator objects.
*/
public class DictionaryFacilitatorProvider {
public static DictionaryFacilitator getDictionaryFacilitator(boolean isNeededForSpellChecking) {
return new DictionaryFacilitatorImpl();
}
}

View file

@ -0,0 +1,28 @@
/*
* Copyright (C) 2013 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.latin.about;
import android.app.Fragment;
/**
* Dummy class of AboutPreferences. Never use this.
*/
public final class AboutPreferences extends Fragment {
private AboutPreferences() {
// Prevents this from being instantiated
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright (C) 2014 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.latin.accounts;
import android.support.annotation.NonNull;
import javax.annotation.Nullable;
/**
* Handles changes to account used to sign in to the keyboard.
* e.g. account switching/sign-in/sign-out from the keyboard
* user toggling the sync preference.
*/
public class AccountStateChangedListener {
/**
* Called when the current account being used in keyboard is signed out.
*
* @param oldAccount the account that was signed out of.
*/
public static void onAccountSignedOut(@NonNull String oldAccount) {
}
/**
* Called when the user signs-in to the keyboard.
* This may be called when the user switches accounts to sign in with a different account.
*
* @param oldAccount the previous account that was being used for sign-in.
* May be null for a fresh sign-in.
* @param newAccount the account being used for sign-in.
*/
public static void onAccountSignedIn(@Nullable String oldAccount, @NonNull String newAccount) {
}
/**
* Called when the user toggles the sync preference.
*
* @param account the account being used for sync.
* @param syncEnabled indicates whether sync has been enabled or not.
*/
public static void onSyncPreferenceChanged(@Nullable String account, boolean syncEnabled) {
}
/**
* Forces an immediate sync to happen.
* This should only be used for debugging purposes.
*
* @param account the account to use for sync.
*/
public static void forceSync(@Nullable String account) {
}
/**
* Forces an immediate deletion of user's data.
* This should only be used for debugging purposes.
*
* @param account the account to use for sync.
*/
public static void forceDelete(@Nullable String account) {
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2014 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.latin.accounts;
import android.content.Context;
import javax.annotation.Nonnull;
/**
* Utility class for retrieving accounts that may be used for login.
*/
public class LoginAccountUtils {
/**
* This defines the type of account this class deals with.
* This account type is used when listing the accounts available on the device for login.
*/
public static final String ACCOUNT_TYPE = "";
private LoginAccountUtils() {
// This utility class is not publicly instantiable.
}
/**
* Get the accounts available for login.
*
* @return an array of accounts. Empty (never null) if no accounts are available for login.
*/
@Nonnull
@SuppressWarnings("unused")
public static String[] getAccountsForLogin(final Context context) {
return new String[0];
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2014 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.latin.define;
import android.content.SharedPreferences;
public final class DebugFlags {
public static final boolean DEBUG_ENABLED = false;
private DebugFlags() {
// This class is not publicly instantiable.
}
@SuppressWarnings("unused")
public static void init(final SharedPreferences prefs) {
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2015 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.latin.define;
/**
* Decoder specific constants for LatinIme.
*/
public class DecoderSpecificConstants {
// Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
public static final int DICTIONARY_MAX_WORD_LENGTH = 48;
// (MAX_PREV_WORD_COUNT_FOR_N_GRAM + 1)-gram is supported in Java side. Needs to modify
// MAX_PREV_WORD_COUNT_FOR_N_GRAM in native/jni/src/defines.h for suggestions.
public static final int MAX_PREV_WORD_COUNT_FOR_N_GRAM = 3;
public static final String DECODER_DICT_SUFFIX = "";
public static final boolean SHOULD_VERIFY_MAGIC_NUMBER = true;
public static final boolean SHOULD_VERIFY_CHECKSUM = true;
public static final boolean SHOULD_USE_DICT_VERSION = true;
public static final boolean SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION = false;
public static final boolean SHOULD_REMOVE_PREVIOUSLY_REJECTED_SUGGESTION = true;
}

View file

@ -0,0 +1,25 @@
/*
* Copyright (C) 2011 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.latin.define;
public final class JniLibName {
private JniLibName() {
// This class is not publicly instantiable.
}
public static final String JNI_LIB_NAME = "jni_latinime";
}

View file

@ -0,0 +1,58 @@
/*
* 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.latin.define;
public final class ProductionFlags {
private ProductionFlags() {
// This class is not publicly instantiable.
}
public static final boolean IS_HARDWARE_KEYBOARD_SUPPORTED = false;
/**
* Include all suggestions from all dictionaries in
* {@link com.android.inputmethod.latin.SuggestedWords#mRawSuggestions}.
*/
public static final boolean INCLUDE_RAW_SUGGESTIONS = false;
/**
* When false, the metrics logging is not yet ready to be enabled.
*/
public static final boolean IS_METRICS_LOGGING_SUPPORTED = false;
/**
* When {@code false}, the split keyboard is not yet ready to be enabled.
*/
public static final boolean IS_SPLIT_KEYBOARD_SUPPORTED = true;
/**
* When {@code false}, account sign-in in keyboard is not yet ready to be enabled.
*/
public static final boolean ENABLE_ACCOUNT_SIGN_IN = false;
/**
* When {@code true}, user history dictionary sync feature is ready to be enabled.
*/
public static final boolean ENABLE_USER_HISTORY_DICTIONARY_SYNC =
ENABLE_ACCOUNT_SIGN_IN && false;
/**
* When {@code true}, the IME maintains per account {@link UserHistoryDictionary}.
*/
public static final boolean ENABLE_PER_ACCOUNT_USER_HISTORY_DICTIONARY =
ENABLE_ACCOUNT_SIGN_IN && false;
}

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2013 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.latin.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceFragment;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.latin.RichInputMethodSubtype;
import com.android.inputmethod.latin.RichInputMethodManager;
import javax.annotation.Nonnull;
/**
* Utility class for managing additional features settings.
*/
@SuppressWarnings("unused")
public class AdditionalFeaturesSettingUtils {
public static final int ADDITIONAL_FEATURES_SETTINGS_SIZE = 0;
private AdditionalFeaturesSettingUtils() {
// This utility class is not publicly instantiable.
}
public static void addAdditionalFeaturesPreferences(
final Context context, final PreferenceFragment settingsFragment) {
// do nothing.
}
public static void readAdditionalFeaturesPreferencesIntoArray(final Context context,
final SharedPreferences prefs, final int[] additionalFeaturesPreferences) {
// do nothing.
}
@Nonnull
public static RichInputMethodSubtype createRichInputMethodSubtype(
@Nonnull final RichInputMethodManager imm,
@Nonnull final InputMethodSubtype subtype,
final Context context) {
return new RichInputMethodSubtype(subtype);
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 2014 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.latin.touchinputconsumer;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.DictionaryFacilitator;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer;
import java.util.Locale;
/**
* Stub for GestureConsumer.
* <br>
* The methods of this class should only be called from a single thread, e.g.,
* the UI Thread.
*/
@SuppressWarnings("unused")
public class GestureConsumer {
public static final GestureConsumer NULL_GESTURE_CONSUMER =
new GestureConsumer();
public static GestureConsumer newInstance(
final EditorInfo editorInfo, final PrivateCommandPerformer commandPerformer,
final Locale locale, final Keyboard keyboard) {
return GestureConsumer.NULL_GESTURE_CONSUMER;
}
private GestureConsumer() {
}
public boolean willConsume() {
return false;
}
public void onInit(final Locale locale, final Keyboard keyboard) {
}
public void onGestureStarted(final Locale locale, final Keyboard keyboard) {
}
public void onGestureCanceled() {
}
public void onGestureCompleted(final InputPointers inputPointers) {
}
public void onImeSuggestionsProcessed(final SuggestedWords suggestedWords,
final int composingStart, final int composingLength,
final DictionaryFacilitator dictionaryFacilitator) {
}
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 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.latin.utils;
import com.android.inputmethod.latin.AssetFileAddress;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
import java.io.File;
public class DictionaryHeaderUtils {
public static int getContentVersion(AssetFileAddress fileAddress) {
final DictionaryHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(
new File(fileAddress.mFilename), fileAddress.mOffset, fileAddress.mLength);
return Integer.parseInt(header.mVersionString);
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2013 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.latin.utils;
import android.content.Context;
import android.content.Intent;
@SuppressWarnings("unused")
public class FeedbackUtils {
public static boolean isHelpAndFeedbackFormSupported() {
return false;
}
public static void showHelpAndFeedbackForm(Context context) {
}
public static int getAboutKeyboardTitleResId() {
return 0;
}
public static Intent getAboutKeyboardIntent(Context context) {
return null;
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 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.latin.utils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
public final class FileTransforms {
public static OutputStream getCryptedStream(OutputStream out) {
// Crypt the stream.
return out;
}
public static InputStream getDecryptedStream(InputStream in) {
// Decrypt the stream.
return in;
}
public static InputStream getUncompressedStream(InputStream in) throws IOException {
return new GZIPInputStream(in);
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2014 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.latin.utils;
import android.content.Context;
import com.android.inputmethod.annotations.UsedForTesting;
public class ManagedProfileUtils {
private static ManagedProfileUtils INSTANCE = new ManagedProfileUtils();
private static ManagedProfileUtils sTestInstance;
private ManagedProfileUtils() {
// This utility class is not publicly instantiable.
}
@UsedForTesting
public static void setTestInstance(final ManagedProfileUtils testInstance) {
sTestInstance = testInstance;
}
public static ManagedProfileUtils getInstance() {
return sTestInstance == null ? INSTANCE : sTestInstance;
}
public boolean hasWorkProfile(final Context context) {
return false;
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2013 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.latin.utils;
import com.android.inputmethod.latin.R;
import android.content.Context;
/**
* Helper class to get the metadata URI and the additional ID.
*/
@SuppressWarnings("unused")
public class MetadataFileUriGetter {
private MetadataFileUriGetter() {
// This helper class is not instantiable.
}
public static String getMetadataUri(final Context context) {
return context.getString(R.string.dictionary_pack_metadata_uri);
}
public static String getMetadataAdditionalId(final Context context) {
return "";
}
}

View file

@ -0,0 +1,110 @@
/*
* Copyright (C) 2014 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.latin.utils;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.latin.DictionaryFacilitator;
import com.android.inputmethod.latin.RichInputMethodManager;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.settings.SettingsValues;
import javax.annotation.Nullable;
@SuppressWarnings("unused")
public final class StatsUtils {
private StatsUtils() {
// Intentional empty constructor.
}
public static void onCreate(final SettingsValues settingsValues,
RichInputMethodManager richImm) {
}
public static void onPickSuggestionManually(final SuggestedWords suggestedWords,
final SuggestedWords.SuggestedWordInfo suggestionInfo,
final DictionaryFacilitator dictionaryFacilitator) {
}
public static void onBackspaceWordDelete(int wordLength) {
}
public static void onBackspacePressed(int lengthToDelete) {
}
public static void onBackspaceSelectedText(int selectedTextLength) {
}
public static void onDeleteMultiCharInput(int multiCharLength) {
}
public static void onRevertAutoCorrect() {
}
public static void onRevertDoubleSpacePeriod() {
}
public static void onRevertSwapPunctuation() {
}
public static void onFinishInputView() {
}
public static void onCreateInputView() {
}
public static void onStartInputView(int inputType, int displayOrientation, boolean restarting) {
}
public static void onAutoCorrection(final String typedWord, final String autoCorrectionWord,
final boolean isBatchInput, final DictionaryFacilitator dictionaryFacilitator,
final String prevWordsContext) {
}
public static void onWordCommitUserTyped(final String commitWord, final boolean isBatchMode) {
}
public static void onWordCommitAutoCorrect(final String commitWord, final boolean isBatchMode) {
}
public static void onWordCommitSuggestionPickedManually(
final String commitWord, final boolean isBatchMode) {
}
public static void onDoubleSpacePeriod() {
}
public static void onLoadSettings(SettingsValues settingsValues) {
}
public static void onInvalidWordIdentification(final String invalidWord) {
}
public static void onSubtypeChanged(final InputMethodSubtype oldSubtype,
final InputMethodSubtype newSubtype) {
}
public static void onSettingsActivity(final String entryPoint) {
}
public static void onInputConnectionLaggy(final int operation, final long duration) {
}
public static void onDecoderLaggy(final int operation, final long duration) {
}
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2014 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.latin.utils;
import android.content.Context;
import com.android.inputmethod.latin.DictionaryFacilitator;
import com.android.inputmethod.latin.settings.SettingsValues;
@SuppressWarnings("unused")
public class StatsUtilsManager {
private static final StatsUtilsManager sInstance = new StatsUtilsManager();
private static StatsUtilsManager sTestInstance = null;
/**
* @return the singleton instance of {@link StatsUtilsManager}.
*/
public static StatsUtilsManager getInstance() {
return sTestInstance != null ? sTestInstance : sInstance;
}
public static void setTestInstance(final StatsUtilsManager testInstance) {
sTestInstance = testInstance;
}
public void onCreate(final Context context, final DictionaryFacilitator dictionaryFacilitator) {
}
public void onLoadSettings(final Context context, final SettingsValues settingsValues) {
}
public void onStartInputView() {
}
public void onFinishInputView() {
}
public void onDestroy(final Context context) {
}
}

View file

@ -0,0 +1,46 @@
# Copyright (C) 2011 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.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src ../java-overridable/src)
LOCAL_PACKAGE_NAME := LatinIME
LOCAL_CERTIFICATE := shared
LOCAL_JNI_SHARED_LIBRARIES := libjni_latinime
LOCAL_STATIC_JAVA_LIBRARIES := \
android-common inputmethod-common jsr305 latinime-common
LOCAL_STATIC_ANDROID_LIBRARIES := \
android-support-v4
LOCAL_USE_AAPT2 := true
# Do not compress dictionary files to mmap dict data runtime
LOCAL_AAPT_FLAGS := -0 .dict
# Include all the resources regardless of system supported locales
LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true
LOCAL_SDK_VERSION := current
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
coreApp="true"
package="com.android.inputmethod.latin">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_STATS" />
<uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
<!-- A signature-protected permission to ask AOSP Keyboard to close the software keyboard.
To use this, add the following line into calling application's AndroidManifest.xml
<pre>
{@code
<uses-permission android:name="com.android.inputmethod.latin.HIDE_SOFT_INPUT"/>
}
</pre>
then call {@link android.content.Context#sendBroadcast(Intent)} as follows:
<pre>
{@code
sendBroadcast(new Intent("com.android.inputmethod.latin.HIDE_SOFT_INPUT")
.setPackage("com.android.inputmethod.latin"));
}
</pre> -->
<permission android:name="com.android.inputmethod.latin.HIDE_SOFT_INPUT"
android:protectionLevel="signature" />
<application android:label="@string/english_ime_name"
android:icon="@drawable/ic_launcher_keyboard"
android:supportsRtl="true"
android:allowBackup="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
<!-- Services -->
<service android:name="LatinIME"
android:label="@string/english_ime_name"
android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" />
</service>
<service android:name=".spellcheck.AndroidSpellCheckerService"
android:label="@string/spell_checker_service_name"
android:permission="android.permission.BIND_TEXT_SERVICE">
<intent-filter>
<action android:name="android.service.textservice.SpellCheckerService" />
</intent-filter>
<meta-data android:name="android.view.textservice.scs"
android:resource="@xml/spellchecker" />
</service>
<service android:name="com.android.inputmethod.dictionarypack.DictionaryService"
android:label="@string/dictionary_service_name">
</service>
<!-- Activities -->
<activity android:name=".setup.SetupActivity"
android:theme="@style/platformActivityTheme"
android:label="@string/english_ime_name"
android:icon="@drawable/ic_launcher_keyboard"
android:launchMode="singleTask"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".permissions.PermissionsActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:exported="false"
android:taskAffinity="" >
</activity>
<activity android:name=".setup.SetupWizardActivity"
android:theme="@style/platformActivityTheme"
android:label="@string/english_ime_name"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".settings.SettingsActivity"
android:theme="@style/platformSettingsTheme"
android:label="@string/english_ime_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".spellcheck.SpellCheckerSettingsActivity"
android:theme="@style/platformSettingsTheme"
android:label="@string/android_spell_checker_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name="com.android.inputmethod.dictionarypack.DictionarySettingsActivity"
android:theme="@style/platformSettingsTheme"
android:label="@string/dictionary_settings_title"
android:uiOptions="splitActionBarWhenNarrow">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<activity android:name="com.android.inputmethod.dictionarypack.DownloadOverMeteredDialog"
android:theme="@style/platformActivityTheme"
android:label="@string/dictionary_install_over_metered_network_prompt">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<!-- Unexported activity used for tests. -->
<activity android:name=".settings.TestFragmentActivity"
android:exported="false" />
<!-- Broadcast receivers -->
<receiver android:name="SystemBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.USER_INITIALIZE" />
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
<receiver android:name="DictionaryPackInstallBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="com.android.inputmethod.dictionarypack.aosp.UNKNOWN_CLIENT" />
</intent-filter>
</receiver>
<receiver android:name="com.android.inputmethod.dictionarypack.EventHandler">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
<action android:name="android.intent.action.DATE_CHANGED" />
<action android:name="com.android.inputmethod.dictionarypack.aosp.UPDATE_NOW" />
<action android:name="com.android.inputmethod.dictionarypack.aosp.INIT_AND_UPDATE_NOW" />
</intent-filter>
</receiver>
<!-- Broadcast receiver for AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION. -->
<receiver android:name=".accounts.AccountsChangedReceiver">
<intent-filter>
<action android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
</intent-filter>
</receiver>
<!-- Content providers -->
<provider android:name="com.android.inputmethod.dictionarypack.DictionaryProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="@string/authority"
android:multiprocess="false"
android:label="@string/dictionary_provider_name">
</provider>
</application>
</manifest>

View file

@ -0,0 +1,192 @@
Copyright (c) 2008, 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Includes Dictionaries © Lexiteria LLC. Used by permission.

View file

@ -0,0 +1,28 @@
# Keep classes and methods that have the @UsedForTesting annotation
-keep @com.android.inputmethod.annotations.UsedForTesting class *
-keepclassmembers class * {
@com.android.inputmethod.annotations.UsedForTesting *;
}
# Keep classes and methods that have the @ExternallyReferenced annotation
-keep @com.android.inputmethod.annotations.ExternallyReferenced class *
-keepclassmembers class * {
@com.android.inputmethod.annotations.ExternallyReferenced *;
}
# Keep native methods
-keepclassmembers class * {
native <methods>;
}
# Keep classes that are used as a parameter type of methods that are also marked as keep
# to preserve changing those methods' signature.
-keep class com.android.inputmethod.latin.AssetFileAddress
-keep class com.android.inputmethod.latin.Dictionary
-keep class com.android.inputmethod.latin.NgramContext
-keep class com.android.inputmethod.latin.makedict.ProbabilityInfo
-keep class com.android.inputmethod.latin.utils.LanguageModelParam
# TODO: remove once used in code.
-keep class com.android.inputmethod.keyboard.KeyboardLayout { *; }

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="altCodeKeyWhileTypingAnimAlpha"
android:valueType="intType"
android:duration="1000"
android:valueFrom="128"
android:valueTo="255" />

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="altCodeKeyWhileTypingAnimAlpha"
android:valueType="intType"
android:duration="3000"
android:valueFrom="255"
android:valueTo="128" />

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2014, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="0.94" />
<objectAnimator
android:propertyName="scaleY"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="0.94" />
</set>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2014, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="1.00" />
<objectAnimator
android:propertyName="scaleY"
android:duration="53"
android:valueFrom="1.00"
android:valueTo="0.94" />
</set>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2014, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="17"
android:valueFrom="0.98"
android:valueTo="1.00" />
<objectAnimator
android:propertyName="scaleY"
android:duration="17"
android:valueFrom="0.98"
android:valueTo="1.00" />
</set>

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2014, 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.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:duration="17"
android:valueFrom="1.00"
android:valueTo="1.00" />
<objectAnimator
android:propertyName="scaleY"
android:duration="17"
android:valueFrom="0.98"
android:valueTo="1.00" />
</set>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 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.
*/
-->
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="languageOnSpacebarAnimAlpha"
android:valueType="intType"
android:startOffset="1200"
android:duration="200"
android:valueFrom="255"
android:valueTo="@integer/config_language_on_spacebar_final_alpha" />

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2013, 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.
*/
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_focused="true"
android:color="@color/setup_text_action" />
<item
android:state_pressed="true"
android:color="@color/setup_text_action" />
<item
android:color="@color/setup_step_background" />
</selector>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2013, 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.
*/
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_focused="true"
android:color="@color/setup_step_background" />
<item
android:state_pressed="true"
android:color="@color/setup_step_background" />
<item
android:color="@color/setup_text_action" />
</selector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 553 B

Some files were not shown because too many files have changed in this diff Show more