Pending onStartInputView only if the EditorInfo is identical

Bug: 5604372
Change-Id: I2a88cf15b07eebd29e43e460f6ec758432181b01
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
index 4a2542d..dcebb1c 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java
@@ -116,8 +116,8 @@
      * @return {@code true} if the device should not speak text (eg.
      *         non-control) characters
      */
-    public boolean shouldObscureInput(EditorInfo attribute) {
-        if (attribute == null)
+    public boolean shouldObscureInput(EditorInfo editorInfo) {
+        if (editorInfo == null)
             return false;
 
         // Always speak if the user is listening through headphones.
@@ -125,7 +125,7 @@
             return false;
 
         // Don't speak if the IME is connected to a password field.
-        return InputTypeCompatUtils.isPasswordInputType(attribute.inputType);
+        return InputTypeCompatUtils.isPasswordInputType(editorInfo.inputType);
     }
 
     /**
@@ -159,11 +159,11 @@
      * Handles speaking the "connect a headset to hear passwords" notification
      * when connecting to a password field.
      *
-     * @param attribute The input connection's editor info attribute.
+     * @param editorInfo The input connection's editor info attribute.
      * @param restarting Whether the connection is being restarted.
      */
-    public void onStartInputViewInternal(EditorInfo attribute, boolean restarting) {
-        if (shouldObscureInput(attribute)) {
+    public void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+        if (shouldObscureInput(editorInfo)) {
             final CharSequence text = mContext.getText(R.string.spoken_use_headphones);
             speak(text);
         }
diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
index 3f8c2ef..a013ebc 100644
--- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
+++ b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java
@@ -695,12 +695,12 @@
                 && !mVoiceInput.isBlacklistedField(fieldContext);
     }
 
-    private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) {
+    private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo editorInfo) {
         @SuppressWarnings("deprecation")
         final boolean noMic = Utils.inPrivateImeOptions(null,
-                LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, attribute)
+                LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)
                 || Utils.inPrivateImeOptions(mService.getPackageName(),
-                        LatinIME.IME_OPTION_NO_MICROPHONE, attribute);
+                        LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo);
         return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic
                 && SpeechRecognizer.isRecognitionAvailable(mService);
     }
@@ -709,7 +709,7 @@
         return SpeechRecognizer.isRecognitionAvailable(context);
     }
 
-    public void loadSettings(EditorInfo attribute, SharedPreferences sp) {
+    public void loadSettings(EditorInfo editorInfo, SharedPreferences sp) {
         if (!VOICE_INSTALLED) {
             return;
         }
@@ -723,7 +723,7 @@
         final String voiceMode = sp.getString(PREF_VOICE_MODE,
                 mService.getString(R.string.voice_mode_main));
         mVoiceButtonEnabled = !voiceMode.equals(mService.getString(R.string.voice_mode_off))
-                && shouldShowVoiceButton(makeFieldContext(), attribute);
+                && shouldShowVoiceButton(makeFieldContext(), editorInfo);
         mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main));
     }
 
diff --git a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
index 3c79cc2..fd2cf3d 100644
--- a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
+++ b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java
@@ -43,10 +43,10 @@
 
     Bundle mFieldInfo;
 
-    public FieldContext(InputConnection conn, EditorInfo info,
+    public FieldContext(InputConnection conn, EditorInfo editorInfo,
             String selectedLanguage, String[] enabledLanguages) {
         mFieldInfo = new Bundle();
-        addEditorInfoToBundle(info, mFieldInfo);
+        addEditorInfoToBundle(editorInfo, mFieldInfo);
         addInputConnectionToBundle(conn, mFieldInfo);
         addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo);
         if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString());
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index cf06371..8408577 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -58,15 +58,15 @@
     public final int mImeAction;
 
     public final String mXmlName;
-    public final EditorInfo mAttribute;
+    public final EditorInfo mEditorInfo;
 
     private final int mHashCode;
 
     public KeyboardId(String xmlName, int xmlId, Locale locale, int orientation, int width,
-            int mode, EditorInfo attribute, boolean hasSettingsKey, int f2KeyMode,
+            int mode, EditorInfo editorInfo, boolean hasSettingsKey, int f2KeyMode,
             boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey) {
-        final int inputType = (attribute != null) ? attribute.inputType : 0;
-        final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
+        final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
+        final int imeOptions = (editorInfo != null) ? editorInfo.imeOptions : 0;
         this.mLocale = locale;
         this.mOrientation = orientation;
         this.mWidth = width;
@@ -89,7 +89,7 @@
                 EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
 
         this.mXmlName = xmlName;
-        this.mAttribute = attribute;
+        this.mEditorInfo = editorInfo;
 
         this.mHashCode = Arrays.hashCode(new Object[] {
                 locale,
@@ -109,7 +109,7 @@
     }
 
     public KeyboardId cloneWithNewXml(String xmlName, int xmlId) {
-        return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mAttribute,
+        return new KeyboardId(xmlName, xmlId, mLocale, mOrientation, mWidth, mMode, mEditorInfo,
                 false, F2KEY_MODE_NONE, false, false, false);
     }
 
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 049b316..dc5ec2d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -409,6 +409,7 @@
         private boolean mHasPendingStartInput;
         private boolean mHasPendingFinishInputView;
         private boolean mHasPendingFinishInput;
+        private EditorInfo mAppliedEditorInfo;
 
         public void startOrientationChanging() {
             removeMessages(MSG_PENDING_IMS_CALLBACK);
@@ -424,18 +425,18 @@
             mHasPendingStartInput = false;
         }
 
-        private void executePendingImsCallback(LatinIME latinIme, EditorInfo attribute,
+        private void executePendingImsCallback(LatinIME latinIme, EditorInfo editorInfo,
                 boolean restarting) {
             if (mHasPendingFinishInputView)
                 latinIme.onFinishInputViewInternal(mHasPendingFinishInput);
             if (mHasPendingFinishInput)
                 latinIme.onFinishInputInternal();
             if (mHasPendingStartInput)
-                latinIme.onStartInputInternal(attribute, restarting);
+                latinIme.onStartInputInternal(editorInfo, restarting);
             resetPendingImsCallback();
         }
 
-        public void onStartInput(EditorInfo attribute, boolean restarting) {
+        public void onStartInput(EditorInfo editorInfo, boolean restarting) {
             if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
                 // Typically this is the second onStartInput after orientation changed.
                 mHasPendingStartInput = true;
@@ -446,27 +447,28 @@
                     mPendingSuccesiveImsCallback = true;
                 }
                 final LatinIME latinIme = getOuterInstance();
-                executePendingImsCallback(latinIme, attribute, restarting);
-                latinIme.onStartInputInternal(attribute, restarting);
+                executePendingImsCallback(latinIme, editorInfo, restarting);
+                latinIme.onStartInputInternal(editorInfo, restarting);
             }
         }
 
-        public void onStartInputView(EditorInfo attribute, boolean restarting) {
-             if (hasMessages(MSG_PENDING_IMS_CALLBACK)) {
-                 // Typically this is the second onStartInputView after orientation changed.
-                 resetPendingImsCallback();
-             } else {
-                 if (mPendingSuccesiveImsCallback) {
-                     // This is the first onStartInputView after orientation changed.
-                     mPendingSuccesiveImsCallback = false;
-                     resetPendingImsCallback();
-                     sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
-                             PENDING_IMS_CALLBACK_DURATION);
-                 }
-                 final LatinIME latinIme = getOuterInstance();
-                 executePendingImsCallback(latinIme, attribute, restarting);
-                 latinIme.onStartInputViewInternal(attribute, restarting);
-             }
+        public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
+            if (hasMessages(MSG_PENDING_IMS_CALLBACK) && editorInfo == mAppliedEditorInfo) {
+                // Typically this is the second onStartInputView after orientation changed.
+                resetPendingImsCallback();
+            } else {
+                if (mPendingSuccesiveImsCallback) {
+                    // This is the first onStartInputView after orientation changed.
+                    mPendingSuccesiveImsCallback = false;
+                    resetPendingImsCallback();
+                    sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
+                            PENDING_IMS_CALLBACK_DURATION);
+                }
+                final LatinIME latinIme = getOuterInstance();
+                executePendingImsCallback(latinIme, editorInfo, restarting);
+                latinIme.onStartInputViewInternal(editorInfo, restarting);
+                mAppliedEditorInfo = editorInfo;
+            }
         }
 
         public void onFinishInputView(boolean finishingInput) {
@@ -476,6 +478,7 @@
             } else {
                 final LatinIME latinIme = getOuterInstance();
                 latinIme.onFinishInputViewInternal(finishingInput);
+                mAppliedEditorInfo = null;
             }
         }
 
@@ -703,13 +706,13 @@
     }
 
     @Override
-    public void onStartInput(EditorInfo attribute, boolean restarting) {
-        mHandler.onStartInput(attribute, restarting);
+    public void onStartInput(EditorInfo editorInfo, boolean restarting) {
+        mHandler.onStartInput(editorInfo, restarting);
     }
 
     @Override
-    public void onStartInputView(EditorInfo attribute, boolean restarting) {
-        mHandler.onStartInputView(attribute, restarting);
+    public void onStartInputView(EditorInfo editorInfo, boolean restarting) {
+        mHandler.onStartInputView(editorInfo, restarting);
     }
 
     @Override
@@ -722,19 +725,19 @@
         mHandler.onFinishInput();
     }
 
-    private void onStartInputInternal(EditorInfo attribute, boolean restarting) {
-        super.onStartInput(attribute, restarting);
+    private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) {
+        super.onStartInput(editorInfo, restarting);
     }
 
-    private void onStartInputViewInternal(EditorInfo attribute, boolean restarting) {
-        super.onStartInputView(attribute, restarting);
+    private void onStartInputViewInternal(EditorInfo editorInfo, boolean restarting) {
+        super.onStartInputView(editorInfo, restarting);
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
         LatinKeyboardView inputView = switcher.getKeyboardView();
 
         if (DEBUG) {
-            Log.d(TAG, "onStartInputView: attribute:" + ((attribute == null) ? "none"
+            Log.d(TAG, "onStartInputView: editorInfo:" + ((editorInfo == null) ? "none"
                     : String.format("inputType=0x%08x imeOptions=0x%08x",
-                            attribute.inputType, attribute.imeOptions)));
+                            editorInfo.inputType, editorInfo.imeOptions)));
         }
         // In landscape mode, this method gets called without the input view being created.
         if (inputView == null) {
@@ -744,7 +747,7 @@
         // Forward this event to the accessibility utilities, if enabled.
         final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
         if (accessUtils.isTouchExplorationEnabled()) {
-            accessUtils.onStartInputViewInternal(attribute, restarting);
+            accessUtils.onStartInputViewInternal(editorInfo, restarting);
         }
 
         mSubtypeSwitcher.updateParametersOnStartInputView();
@@ -755,14 +758,14 @@
         // know now whether this is a password text field, because we need to know now whether we
         // want to enable the voice button.
         final VoiceProxy voiceIme = mVoiceProxy;
-        final int inputType = (attribute != null) ? attribute.inputType : 0;
+        final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
         voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType)
                 || InputTypeCompatUtils.isVisiblePasswordInputType(inputType));
 
         // The EditorInfo might have a flag that affects fullscreen mode.
         // Note: This call should be done by InputMethodService?
         updateFullscreenMode();
-        initializeInputAttributes(attribute);
+        initializeInputAttributes(editorInfo);
 
         inputView.closing();
         mEnteredText = null;
@@ -778,12 +781,12 @@
         if (mSuggest != null && mSettingsValues.mAutoCorrectEnabled) {
             mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold);
         }
-        mVoiceProxy.loadSettings(attribute, mPrefs);
+        mVoiceProxy.loadSettings(editorInfo, mPrefs);
         // This will work only when the subtype is not supported.
         LanguageSwitcherProxy.loadSettings();
 
         if (mSubtypeSwitcher.isKeyboardMode()) {
-            switcher.loadKeyboard(attribute, mSettingsValues);
+            switcher.loadKeyboard(editorInfo, mSettingsValues);
         }
 
         if (mSuggestionsView != null)
@@ -803,10 +806,10 @@
         if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
 
-    private void initializeInputAttributes(EditorInfo attribute) {
-        if (attribute == null)
+    private void initializeInputAttributes(EditorInfo editorInfo) {
+        if (editorInfo == null)
             return;
-        final int inputType = attribute.inputType;
+        final int inputType = editorInfo.inputType;
         if (inputType == InputType.TYPE_NULL) {
             // TODO: We should honor TYPE_NULL specification.
             Log.i(TAG, "InputType.TYPE_NULL is specified");
@@ -815,7 +818,7 @@
         final int variation = inputType & InputType.TYPE_MASK_VARIATION;
         if (inputClass == 0) {
             Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x imeOptions=0x%08x",
-                    inputType, attribute.imeOptions));
+                    inputType, editorInfo.imeOptions));
         }
 
         mInsertSpaceOnPickSuggestionManually = false;
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index e5a041f..7d6efa5 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -301,9 +301,9 @@
             return mShowSettingsKey;
         }
 
-        public boolean isVoiceKeyEnabled(EditorInfo attribute) {
+        public boolean isVoiceKeyEnabled(EditorInfo editorInfo) {
             final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
-            final int inputType = (attribute != null) ? attribute.inputType : 0;
+            final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
             return shortcutImeEnabled && mVoiceKeyEnabled
                     && !InputTypeCompatUtils.isPasswordInputType(inputType);
         }