Step 28-A Introduce the session Id to getSuggestion

Change-Id: I39d9bf1a7c272eb16d6ed4698f52457579b40f10
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index f0f5cd3..cdaffa6 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.text.TextUtils;
+import android.util.SparseArray;
 
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
@@ -51,6 +52,7 @@
     private static final int TYPED_LETTER_MULTIPLIER = 2;
 
     private long mNativeDict;
+    private final Locale mLocale;
     private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
     // TODO: The below should be int[] mOutputCodePoints
     private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_RESULTS];
@@ -59,7 +61,22 @@
     private final int[] mOutputTypes = new int[MAX_RESULTS];
 
     private final boolean mUseFullEditDistance;
-    private final DicTraverseSession mDicTraverseSession;
+
+    private final SparseArray<DicTraverseSession> mDicTraverseSessions =
+            new SparseArray<DicTraverseSession>();
+    private DicTraverseSession getTraverseSession(int traverseSessionId) {
+        DicTraverseSession traverseSession = mDicTraverseSessions.get(traverseSessionId);
+        if (traverseSession == null) {
+            synchronized(mDicTraverseSessions) {
+                traverseSession = mDicTraverseSessions.get(traverseSessionId);
+                if (traverseSession == null) {
+                    traverseSession = new DicTraverseSession(mLocale, mNativeDict);
+                    mDicTraverseSessions.put(traverseSessionId, traverseSession);
+                }
+            }
+        }
+        return traverseSession;
+    }
 
     /**
      * Constructor for the binary dictionary. This is supposed to be called from the
@@ -76,10 +93,9 @@
             final String filename, final long offset, final long length,
             final boolean useFullEditDistance, final Locale locale, final String dictType) {
         super(dictType);
+        mLocale = locale;
         mUseFullEditDistance = useFullEditDistance;
         loadDictionary(filename, offset, length);
-        mDicTraverseSession = new DicTraverseSession(locale);
-        mDicTraverseSession.initSession(mNativeDict);
     }
 
     static {
@@ -109,7 +125,14 @@
     @Override
     public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final CharSequence prevWord, final ProximityInfo proximityInfo) {
+        return getSuggestionsWithSessionId(composer, prevWord, proximityInfo, 0);
+    }
+
+    @Override
+    public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
+            final CharSequence prevWord, final ProximityInfo proximityInfo, int sessionId) {
         if (!isValidDictionary()) return null;
+
         Arrays.fill(mInputCodePoints, WordComposer.NOT_A_CODE);
         // TODO: toLowerCase in the native code
         final int[] prevWordCodePointArray = (null == prevWord)
@@ -128,7 +151,7 @@
         final int codesSize = isGesture ? ips.getPointerSize() : composerSize;
         // proximityInfo and/or prevWordForBigrams may not be null.
         final int tmpCount = getSuggestionsNative(mNativeDict,
-                proximityInfo.getNativeProximityInfo(), mDicTraverseSession.getSession(),
+                proximityInfo.getNativeProximityInfo(), getTraverseSession(sessionId).getSession(),
                 ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(),
                 mInputCodePoints, codesSize, 0 /* commitPoint */, isGesture, prevWordCodePointArray,
                 mUseFullEditDistance, mOutputChars, mOutputScores, mSpaceIndices, mOutputTypes);
@@ -187,7 +210,13 @@
 
     @Override
     public synchronized void close() {
-        mDicTraverseSession.close();
+        for (int i = 0; i < mDicTraverseSessions.size(); ++i) {
+            final int key = mDicTraverseSessions.keyAt(i);
+            final DicTraverseSession traverseSession = mDicTraverseSessions.get(key);
+            if (traverseSession != null) {
+                traverseSession.close();
+            }
+        }
         closeInternal();
     }
 
diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
index c768153..359da72 100644
--- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java
+++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
@@ -22,6 +22,7 @@
     static {
         JniUtils.loadNativeLibrary();
     }
+
     private native long setDicTraverseSessionNative(String locale);
     private native void initDicTraverseSessionNative(long nativeDicTraverseSession,
             long dictionary, int[] previousWord, int previousWordLength);
@@ -29,9 +30,10 @@
 
     private long mNativeDicTraverseSession;
 
-    public DicTraverseSession(Locale locale) {
+    public DicTraverseSession(Locale locale, long dictionary) {
         mNativeDicTraverseSession = createNativeDicTraverseSession(
                 locale != null ? locale.toString() : "");
+        initSession(dictionary);
     }
 
     public long getSession() {
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index 60fe17b..2565dfc 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -62,6 +62,13 @@
     abstract public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
             final CharSequence prevWord, final ProximityInfo proximityInfo);
 
+    // The default implementation of this method ignores sessionId.
+    // Subclasses that want to use sessionId need to override this method.
+    public ArrayList<SuggestedWordInfo> getSuggestionsWithSessionId(final WordComposer composer,
+            final CharSequence prevWord, final ProximityInfo proximityInfo, int sessionId) {
+        return getSuggestions(composer, prevWord, proximityInfo);
+    }
+
     /**
      * Checks if the given word occurs in the dictionary
      * @param word the word to search for. The search should be case-insensitive.
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 8a2341d..1f43c6d 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -169,9 +169,17 @@
     public SuggestedWords getSuggestedWords(
             final WordComposer wordComposer, CharSequence prevWordForBigram,
             final ProximityInfo proximityInfo, final boolean isCorrectionEnabled) {
+        return getSuggestedWordsWithSessionId(
+                wordComposer, prevWordForBigram, proximityInfo, isCorrectionEnabled, 0);
+    }
+
+    public SuggestedWords getSuggestedWordsWithSessionId(
+            final WordComposer wordComposer, CharSequence prevWordForBigram,
+            final ProximityInfo proximityInfo, final boolean isCorrectionEnabled, int sessionId) {
         LatinImeLogger.onStartSuggestion(prevWordForBigram);
         if (wordComposer.isBatchMode()) {
-            return getSuggestedWordsForBatchInput(wordComposer, prevWordForBigram, proximityInfo);
+            return getSuggestedWordsForBatchInput(
+                    wordComposer, prevWordForBigram, proximityInfo, sessionId);
         } else {
             return getSuggestedWordsForTypingInput(wordComposer, prevWordForBigram, proximityInfo,
                     isCorrectionEnabled);
@@ -306,7 +314,7 @@
     // Retrieves suggestions for the batch input.
     private SuggestedWords getSuggestedWordsForBatchInput(
             final WordComposer wordComposer, CharSequence prevWordForBigram,
-            final ProximityInfo proximityInfo) {
+            final ProximityInfo proximityInfo, int sessionId) {
         final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator,
                 MAX_SUGGESTIONS);
 
@@ -318,8 +326,8 @@
                 continue;
             }
             final Dictionary dictionary = mDictionaries.get(key);
-            suggestionsSet.addAll(dictionary.getSuggestions(
-                    wordComposer, prevWordForBigram, proximityInfo));
+            suggestionsSet.addAll(dictionary.getSuggestionsWithSessionId(
+                    wordComposer, prevWordForBigram, proximityInfo, sessionId));
         }
 
         final ArrayList<SuggestedWordInfo> suggestionsContainer =