am bced8270: Merge "Fix calculation of more keys keyboard position based on key preview" into jb-dev

* commit 'bced82709ad262d59ec523439ea7b22b18c5335b':
  Fix calculation of more keys keyboard position based on key preview
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 213c0ac..e8211ae 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -705,6 +705,10 @@
 
     @Override
     public void onWindowHidden() {
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.latinIME_onWindowHidden(mLastSelectionStart, mLastSelectionEnd,
+                    getCurrentInputConnection());
+        }
         super.onWindowHidden();
         KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
         if (inputView != null) inputView.closing();
@@ -735,7 +739,6 @@
             int composingSpanStart, int composingSpanEnd) {
         super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
                 composingSpanStart, composingSpanEnd);
-
         if (DEBUG) {
             Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
                     + ", ose=" + oldSelEnd
@@ -747,9 +750,15 @@
                     + ", ce=" + composingSpanEnd);
         }
         if (ProductionFlag.IS_EXPERIMENTAL) {
+            final boolean expectingUpdateSelectionFromLogger =
+                    ResearchLogger.getAndClearLatinIMEExpectingUpdateSelection();
             ResearchLogger.latinIME_onUpdateSelection(mLastSelectionStart, mLastSelectionEnd,
                     oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
-                    composingSpanEnd);
+                    composingSpanEnd, mExpectingUpdateSelection,
+                    expectingUpdateSelectionFromLogger);
+            if (expectingUpdateSelectionFromLogger) {
+                return;
+            }
         }
 
         // TODO: refactor the following code to be less contrived.
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 566af70..92a9633 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.latin;
 
 import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
 import android.inputmethodservice.InputMethodService;
 import android.os.Build;
 import android.os.Handler;
@@ -29,6 +30,7 @@
 import android.view.MotionEvent;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
 
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.KeyDetector;
@@ -47,6 +49,7 @@
 import java.nio.channels.FileChannel;
 import java.nio.charset.Charset;
 import java.util.Map;
+import java.util.UUID;
 
 /**
  * Logs the use of the LatinIME keyboard.
@@ -59,13 +62,19 @@
 public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
     private static final String TAG = ResearchLogger.class.getSimpleName();
     private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+    private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid";
     private static final boolean DEBUG = false;
 
     private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager());
+    private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
     public static boolean sIsLogging = false;
     /* package */ final Handler mLoggingHandler;
     private InputMethodService mIms;
 
+    // set when LatinIME should ignore a onUpdateSelection() callback that
+    // arises from operations in this class
+    private static boolean mLatinIMEExpectingUpdateSelection = false;
+
     /**
      * Isolates management of files. This variable should never be null, but can be changed
      * to support testing.
@@ -336,6 +345,7 @@
         private static final boolean LATINIME_DELETESURROUNDINGTEXT_ENABLED = DEFAULT_ENABLED;
         private static final boolean LATINIME_DOUBLESPACEAUTOPERIOD_ENABLED = DEFAULT_ENABLED;
         private static final boolean LATINIME_ONDISPLAYCOMPLETIONS_ENABLED = DEFAULT_ENABLED;
+        private static final boolean LATINIME_ONWINDOWHIDDEN_ENABLED = DEFAULT_ENABLED;
         private static final boolean LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED = DEFAULT_ENABLED;
         private static final boolean LATINIME_ONUPDATESELECTION_ENABLED = DEFAULT_ENABLED;
         private static final boolean LATINIME_PERFORMEDITORACTION_ENABLED = DEFAULT_ENABLED;
@@ -528,11 +538,50 @@
         }
     }
 
+    /* package */ static boolean getAndClearLatinIMEExpectingUpdateSelection() {
+        boolean returnValue = mLatinIMEExpectingUpdateSelection;
+        mLatinIMEExpectingUpdateSelection = false;
+        return returnValue;
+    }
+
+    public static void latinIME_onWindowHidden(final int savedSelectionStart,
+            final int savedSelectionEnd, final InputConnection ic) {
+        if (UnsLogGroup.LATINIME_ONWINDOWHIDDEN_ENABLED) {
+            if (ic != null) {
+                ic.beginBatchEdit();
+                ic.performContextMenuAction(android.R.id.selectAll);
+                CharSequence charSequence = ic.getSelectedText(0);
+                ic.setSelection(savedSelectionStart, savedSelectionEnd);
+                ic.endBatchEdit();
+                mLatinIMEExpectingUpdateSelection = true;
+                if (TextUtils.isEmpty(charSequence)) {
+                    logUnstructured("LatinIME_onWindowHidden", "<no text>");
+                } else {
+                    if (charSequence.length() > MAX_INPUTVIEW_LENGTH_TO_CAPTURE) {
+                        // do not cut in the middle of a supplementary character
+                        int length = MAX_INPUTVIEW_LENGTH_TO_CAPTURE;
+                        if (!Character.isLetter(charSequence.charAt(length))) {
+                            length--;
+                        }
+                        final CharSequence truncatedCharSequence = charSequence.subSequence(0,
+                                length);
+                        logUnstructured("LatinIME_onWindowHidden", truncatedCharSequence.toString()
+                                + "<truncated>");
+                    } else {
+                        logUnstructured("LatinIME_onWindowHidden", charSequence.toString());
+                    }
+                }
+            }
+        }
+    }
+
     public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
             final SharedPreferences prefs) {
         if (UnsLogGroup.LATINIME_ONSTARTINPUTVIEWINTERNAL_ENABLED) {
             final StringBuilder builder = new StringBuilder();
             builder.append("onStartInputView: editorInfo:");
+            builder.append("\tpackageName=");
+            builder.append(editorInfo.packageName);
             builder.append("\tinputType=");
             builder.append(Integer.toHexString(editorInfo.inputType));
             builder.append("\timeOptions=");
@@ -544,14 +593,28 @@
                 Object value = entry.getValue();
                 builder.append("=" + ((value == null) ? "<null>" : value.toString()));
             }
+            builder.append("\tuuid="); builder.append(getUUID(prefs));
             logUnstructured("LatinIME_onStartInputViewInternal", builder.toString());
         }
     }
 
+    private static String getUUID(final SharedPreferences prefs) {
+        String uuidString = prefs.getString(PREF_RESEARCH_LOGGER_UUID_STRING, null);
+        if (null == uuidString) {
+            UUID uuid = UUID.randomUUID();
+            uuidString = uuid.toString();
+            Editor editor = prefs.edit();
+            editor.putString(PREF_RESEARCH_LOGGER_UUID_STRING, uuidString);
+            editor.apply();
+        }
+        return uuidString;
+    }
+
     public static void latinIME_onUpdateSelection(final int lastSelectionStart,
             final int lastSelectionEnd, final int oldSelStart, final int oldSelEnd,
             final int newSelStart, final int newSelEnd, final int composingSpanStart,
-            final int composingSpanEnd) {
+            final int composingSpanEnd, final boolean expectingUpdateSelection,
+            final boolean expectingUpdateSelectionFromLogger) {
         if (UnsLogGroup.LATINIME_ONUPDATESELECTION_ENABLED) {
             final String s = "onUpdateSelection: oss=" + oldSelStart
                     + ", ose=" + oldSelEnd
@@ -560,7 +623,9 @@
                     + ", nss=" + newSelStart
                     + ", nse=" + newSelEnd
                     + ", cs=" + composingSpanStart
-                    + ", ce=" + composingSpanEnd;
+                    + ", ce=" + composingSpanEnd
+                    + ", eus=" + expectingUpdateSelection
+                    + ", eusfl=" + expectingUpdateSelectionFromLogger;
             logUnstructured("LatinIME_onUpdateSelection", s);
         }
     }
@@ -754,4 +819,4 @@
             logUnstructured("SuggestionsView_setSuggestions", mSuggestedWords.toString());
         }
     }
-}
\ No newline at end of file
+}