- separate dict (uses xml)
- retrieve bigrams that only starts with character typed and neighbor keys
- contacts bigram
- performance measure

bug: 2873133

Change-Id: If97c005b18c82f3fafef50009dd2dfd972b0ab8f
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 4fe80da..bf7ec0d 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -67,8 +67,9 @@
     int *nextLetters = nextLettersArray != NULL ? env->GetIntArrayElements(nextLettersArray, NULL)
             : NULL;
 
-    int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars, frequencies,
-            maxWordLength, maxWords, maxAlternatives, skipPos, nextLetters, nextLettersSize);
+    int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars,
+            frequencies, maxWordLength, maxWords, maxAlternatives, skipPos, nextLetters,
+            nextLettersSize);
 
     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
     env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
@@ -81,20 +82,24 @@
 }
 
 static int latinime_BinaryDictionary_getBigrams
-        (JNIEnv *env, jobject object, jint dict, jcharArray wordArray, jint wordLength,
-         jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxBigrams)
+        (JNIEnv *env, jobject object, jint dict, jcharArray prevWordArray, jint prevWordLength,
+         jintArray inputArray, jint inputArraySize, jcharArray outputArray,
+         jintArray frequencyArray, jint maxWordLength, jint maxBigrams, jint maxAlternatives)
 {
     Dictionary *dictionary = (Dictionary*) dict;
     if (dictionary == NULL) return 0;
 
-    jchar *word = env->GetCharArrayElements(wordArray, NULL);
+    jchar *prevWord = env->GetCharArrayElements(prevWordArray, NULL);
+    int *inputCodes = env->GetIntArrayElements(inputArray, NULL);
     jchar *outputChars = env->GetCharArrayElements(outputArray, NULL);
     int *frequencies = env->GetIntArrayElements(frequencyArray, NULL);
 
-    int count = dictionary->getBigrams((unsigned short*) word, wordLength,
-            (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams);
+    int count = dictionary->getBigrams((unsigned short*) prevWord, prevWordLength, inputCodes,
+            inputArraySize, (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams,
+            maxAlternatives);
 
-    env->ReleaseCharArrayElements(wordArray, word, JNI_ABORT);
+    env->ReleaseCharArrayElements(prevWordArray, prevWord, JNI_ABORT);
+    env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT);
     env->ReleaseCharArrayElements(outputArray, outputChars, 0);
     env->ReleaseIntArrayElements(frequencyArray, frequencies, 0);
 
@@ -130,7 +135,7 @@
     {"closeNative",          "(I)V",            (void*)latinime_BinaryDictionary_close},
     {"getSuggestionsNative", "(I[II[C[IIIII[II)I",  (void*)latinime_BinaryDictionary_getSuggestions},
     {"isValidWordNative",    "(I[CI)Z",         (void*)latinime_BinaryDictionary_isValidWord},
-    {"getBigramsNative",    "(I[CI[C[III)I",         (void*)latinime_BinaryDictionary_getBigrams}
+    {"getBigramsNative",    "(I[CI[II[C[IIII)I",         (void*)latinime_BinaryDictionary_getBigrams}
 };
 
 static int registerNativeMethods(JNIEnv* env, const char* className,
diff --git a/native/src/dictionary.cpp b/native/src/dictionary.cpp
index a1a632f..1a39f585b4 100644
--- a/native/src/dictionary.cpp
+++ b/native/src/dictionary.cpp
@@ -387,13 +387,17 @@
 
 
 int
-Dictionary::getBigrams(unsigned short *prevWord, int prevWordLength, unsigned short *bigramChars,
-                       int *bigramFreq, int maxWordLength, int maxBigrams)
+Dictionary::getBigrams(unsigned short *prevWord, int prevWordLength, int *codes, int codesSize,
+        unsigned short *bigramChars, int *bigramFreq, int maxWordLength, int maxBigrams,
+        int maxAlternatives)
 {
     mBigramFreq = bigramFreq;
     mBigramChars = bigramChars;
+    mInputCodes = codes;
+    mInputLength = codesSize;
     mMaxWordLength = maxWordLength;
     mMaxBigrams = maxBigrams;
+    mMaxAlternatives = maxAlternatives;
 
     if (mBigram == 1 && checkIfDictVersionIsLatest()) {
         int pos = isValidWordRec(DICTIONARY_HEADER_SIZE, prevWord, 0, prevWordLength);
@@ -406,7 +410,7 @@
         int bigramExist = (mDict[pos] & FLAG_BIGRAM_READ);
         if (bigramExist > 0) {
             int nextBigramExist = 1;
-            while (nextBigramExist > 0) {
+            while (nextBigramExist > 0 && bigramCount < maxBigrams) {
                 int bigramAddress = getBigramAddress(&pos, true);
                 int frequency = (FLAG_BIGRAM_FREQ & mDict[pos]);
                 // search for all bigrams and store them
@@ -521,8 +525,27 @@
             break;
         }
     }
+    if (checkFirstCharacter(word)) {
+        addWordBigram(word, depth, frequency);
+    }
+}
 
-    addWordBigram(word, depth, frequency);
+bool
+Dictionary::checkFirstCharacter(unsigned short *word)
+{
+    // Checks whether this word starts with same character or neighboring characters of
+    // what user typed.
+
+    int *inputCodes = mInputCodes;
+    int maxAlt = mMaxAlternatives;
+    while (maxAlt > 0) {
+        if ((unsigned int) *inputCodes == (unsigned int) *word) {
+            return true;
+        }
+        inputCodes++;
+        maxAlt--;
+    }
+    return false;
 }
 
 bool
diff --git a/native/src/dictionary.h b/native/src/dictionary.h
index 2c57429..d13496e 100644
--- a/native/src/dictionary.h
+++ b/native/src/dictionary.h
@@ -39,8 +39,9 @@
     int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies,
             int maxWordLength, int maxWords, int maxAlternatives, int skipPos,
             int *nextLetters, int nextLettersSize);
-    int getBigrams(unsigned short *word, int length, unsigned short *outWords, int *frequencies,
-            int maxWordLength, int maxBigrams);
+    int getBigrams(unsigned short *word, int length, int *codes, int codesSize,
+            unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams,
+            int maxAlternatives);
     bool isValidWord(unsigned short *word, int length);
     void setAsset(void *asset) { mAsset = asset; }
     void *getAsset() { return mAsset; }
@@ -64,6 +65,7 @@
     int wideStrLen(unsigned short *str);
 
     bool sameAsTyped(unsigned short *word, int length);
+    bool checkFirstCharacter(unsigned short *word);
     bool addWord(unsigned short *word, int length, int frequency);
     bool addWordBigram(unsigned short *word, int length, int frequency);
     unsigned short toLowerCase(unsigned short c);