From 1fb28137f43ae083c773c32440981ac61e83fa5d Mon Sep 17 00:00:00 2001
From: satok <satok@google.com>
Date: Wed, 24 Nov 2010 17:32:23 +0900
Subject: [PATCH] Fix a bug at showing warning dialog at the first time when
 IME is trigerred in voice mode

bug: 3226268

Change-Id: Ife7c752ad309ef796d9b7cc32517f00c2bb2af34
---
 .../inputmethod/latin/KeyboardSwitcher.java   |  1 +
 .../android/inputmethod/latin/LatinIME.java   |  3 +-
 .../inputmethod/latin/LatinKeyboardView.java  |  7 +++
 .../inputmethod/latin/SubtypeSwitcher.java    | 11 ++--
 .../inputmethod/voice/VoiceIMEConnector.java  | 51 +++++++++++++++++--
 5 files changed, 62 insertions(+), 11 deletions(-)

diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
index b5dd3eed44..5db6e63d08 100644
--- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
@@ -700,6 +700,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
             mInputView.setOnKeyboardActionListener(mInputMethodService);
             mLayoutId = newLayout;
         }
+        // TODO: Not to post if this function was called from loadKeyboardView
         mInputMethodService.mHandler.post(new Runnable() {
             public void run() {
                 if (mInputView != null) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 6554954ee1..d069e00fb8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -632,8 +632,7 @@ public class LatinIME extends InputMethodService
         checkTutorial(attribute.privateImeOptions);
         inputView.setForeground(true);
 
-        // TODO: Not to show keyboard if IME starts in Voice One shot mode.
-        mVoiceConnector.onStartInputView();
+        mVoiceConnector.onStartInputView(mKeyboardSwitcher.getInputView().getWindowToken());
 
         if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
index 4fcfe01bab..ac68e3c398 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.latin.BaseKeyboard.Key;
+import com.android.inputmethod.voice.VoiceIMEConnector;
 
 import android.content.Context;
 import android.graphics.Canvas;
@@ -366,4 +367,10 @@ public class LatinKeyboardView extends BaseKeyboardView {
             c.drawLine(0, mLastY, getWidth(), mLastY, mPaint);
         }
     }
+
+    @Override
+    protected void onAttachedToWindow() {
+        // Token is available from here.
+        VoiceIMEConnector.getInstance().onAttachedToWindow();
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index df123c9f46..7cf055672d 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -17,6 +17,7 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.voice.SettingsUtil;
+import com.android.inputmethod.voice.VoiceIMEConnector;
 import com.android.inputmethod.voice.VoiceInput;
 
 import android.content.Context;
@@ -189,7 +190,10 @@ public class SubtypeSwitcher {
                 mService.onKeyboardLanguageChanged();
             }
         } else if (isVoiceMode()) {
-            if (languageChanged || modeChanged) {
+            // If needsToShowWarningDialog is true, voice input need to show warning before
+            // show recognition view.
+            if (languageChanged || modeChanged
+                    || VoiceIMEConnector.getInstance().needsToShowWarningDialog()) {
                 if (mVoiceInput != null) {
                     // TODO: Call proper function to trigger VoiceIME
                     mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
@@ -340,16 +344,15 @@ public class SubtypeSwitcher {
     ///////////////////////////
 
     public boolean setVoiceInput(VoiceInput vi) {
-        if (mVoiceInput == null) {
+        if (mVoiceInput == null && vi != null) {
             // TODO: Remove requirements to construct KeyboardSwitcher
             // when IME was enabled with Voice mode
             mService.onKeyboardLanguageChanged();
             mVoiceInput = vi;
-            if (isVoiceMode() && mVoiceInput != null) {
+            if (isVoiceMode()) {
                 if (DBG) {
                     Log.d(TAG, "Set and call voice input.");
                 }
-                // TODO: Call proper function to enable VoiceIME
                 mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
                 return true;
             }
diff --git a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
index 629d4b45e5..359760d3ce 100644
--- a/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
+++ b/java/src/com/android/inputmethod/voice/VoiceIMEConnector.java
@@ -96,6 +96,10 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
         return sInstance;
     }
 
+    public static VoiceIMEConnector getInstance() {
+        return sInstance;
+    }
+
     private void initInternal(LatinIME context, UIHandler h) {
         mContext = context;
         mHandler = h;
@@ -150,18 +154,32 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
 
     private void showVoiceWarningDialog(final boolean swipe, IBinder token,
             final boolean configurationChanging) {
+        if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) {
+            return;
+        }
         AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
         builder.setCancelable(true);
         builder.setIcon(R.drawable.ic_mic_dialog);
         builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+            @Override
             public void onClick(DialogInterface dialog, int whichButton) {
                 mVoiceInput.logKeyboardWarningDialogOk();
                 reallyStartListening(swipe, configurationChanging);
             }
         });
         builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+            @Override
             public void onClick(DialogInterface dialog, int whichButton) {
                 mVoiceInput.logKeyboardWarningDialogCancel();
+                switchToLastInputMethod();
+            }
+        });
+        // When the dialog is dismissed by user's cancellation, swith back to the last input method.
+        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
+            @Override
+            public void onCancel(DialogInterface arg0) {
+                mVoiceInput.logKeyboardWarningDialogCancel();
+                switchToLastInputMethod();
             }
         });
 
@@ -245,6 +263,11 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
         return mRecognizing;
     }
 
+    public boolean needsToShowWarningDialog() {
+        return !mHasUsedVoiceInput
+                || (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale);
+    }
+
     public boolean getAndResetIsShowingHint() {
         boolean ret = mIsShowingHint;
         mIsShowingHint = false;
@@ -425,7 +448,15 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
         }});
     }
 
+    private void switchToLastInputMethod() {
+        IBinder token = mContext.getWindow().getWindow().getAttributes().token;
+        mImm.switchToLastInputMethod(token);
+    }
+
     private void reallyStartListening(boolean swipe, final boolean configurationChanging) {
+        if (!VOICE_INSTALLED) {
+            return;
+        }
         if (!mHasUsedVoiceInput) {
             // The user has started a voice input, so remember that in the
             // future (so we don't show the warning dialog after the first run).
@@ -456,9 +487,9 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
 
     public void startListening(final boolean swipe, IBinder token,
             final boolean configurationChanging) {
+        // TODO: remove swipe which is no longer used.
         if (VOICE_INSTALLED) {
-            if (!mHasUsedVoiceInput ||
-                    (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale)) {
+            if (needsToShowWarningDialog()) {
                 // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel.
                 showVoiceWarningDialog(swipe, token, configurationChanging);
             } else {
@@ -504,7 +535,17 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
         }
     }
 
-    public void onStartInputView() {
+    public void onStartInputView(IBinder token) {
+        // If IME is in voice mode, but still needs to show the voice warning dialog,
+        // keep showing the warning.
+        if (mSubtypeSwitcher.isVoiceMode() && needsToShowWarningDialog() && token != null) {
+            showVoiceWarningDialog(false, token, false);
+        }
+    }
+
+    public void onAttachedToWindow() {
+        // After onAttachedToWindow, we can show the voice warning dialog. See startListening()
+        // above.
         mSubtypeSwitcher.setVoiceInput(mVoiceInput);
     }
 
@@ -513,6 +554,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
             switchToRecognitionStatusView(configurationChanging);
         }
     }
+
     @Override
     public void onCancelVoice() {
         if (mRecognizing) {
@@ -521,8 +563,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
                 // cancellation etc.), onCancelVoice() will be called first. LatinIME thinks it's
                 // still in voice mode. LatinIME needs to call switchToLastInputMethod().
                 // Note that onCancelVoice() will be called again from SubtypeSwitcher.
-                IBinder token = mContext.getWindow().getWindow().getAttributes().token;
-                mImm.switchToLastInputMethod(token);
+                switchToLastInputMethod();
             } else if (mSubtypeSwitcher.isKeyboardMode()) {
                 // If voice mode is being canceled out of LatinIME (i.e. by user's IME switching or
                 // as a result of switchToLastInputMethod() etc.),
-- 
GitLab