Enable voice search in omnibox

  Bug: 6601348

Bring back voice search. Also fixes focus bug for fixed titlebar.

Change-Id: I83c8ad96957b62c23ad0bbb35685712687d11213
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index cfe9a53..c749465 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -870,4 +870,9 @@
         return mBlockFocusAnimations;
     }
 
+    @Override
+    public void onVoiceResult(String result) {
+        mNavigationBar.onVoiceResult(result);
+    }
+
 }
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index 8a00ba3..e901d45 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -52,6 +52,7 @@
 import android.provider.BrowserContract.Images;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Intents.Insert;
+import android.speech.RecognizerIntent;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Patterns;
@@ -129,6 +130,7 @@
     final static int PREFERENCES_PAGE = 3;
     final static int FILE_SELECTED = 4;
     final static int AUTOFILL_SETUP = 5;
+    final static int VOICE_RESULT = 6;
 
     private final static int WAKELOCK_TIMEOUT = 5 * 60 * 1000; // 5 minutes
 
@@ -216,6 +218,8 @@
 
     private boolean mBlockEvents;
 
+    private String mVoiceResult;
+
     public Controller(Activity browser) {
         mActivity = browser;
         mSettings = BrowserSettings.getInstance();
@@ -700,6 +704,10 @@
         mNetworkHandler.onResume();
         WebView.enablePlatformNotifications();
         NfcHandler.register(mActivity, this);
+        if (mVoiceResult != null) {
+            mUi.onVoiceResult(mVoiceResult);
+            mVoiceResult = null;
+        }
     }
 
     private void releaseWakeLock() {
@@ -1190,6 +1198,15 @@
                     }
                 }
                 break;
+            case VOICE_RESULT:
+                if (resultCode == Activity.RESULT_OK && intent != null) {
+                    ArrayList<String> results = intent.getStringArrayListExtra(
+                            RecognizerIntent.EXTRA_RESULTS);
+                    if (results.size() >= 1) {
+                        mVoiceResult = results.get(0);
+                    }
+                }
+                break;
             default:
                 break;
         }
@@ -2804,6 +2821,23 @@
     }
 
     @Override
+    public boolean supportsVoice() {
+        PackageManager pm = mActivity.getPackageManager();
+        List activities = pm.queryIntentActivities(new Intent(
+                RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
+        return activities.size() != 0;
+    }
+
+    @Override
+    public void startVoiceRecognizer() {
+        Intent voice = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+        voice.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
+                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
+        voice.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
+        mActivity.startActivityForResult(voice, VOICE_RESULT);
+    }
+
+    @Override
     public void setBlockEvents(boolean block) {
         mBlockEvents = block;
     }
diff --git a/src/com/android/browser/NavigationBarBase.java b/src/com/android/browser/NavigationBarBase.java
index 37b11c8..7f100ff 100644
--- a/src/com/android/browser/NavigationBarBase.java
+++ b/src/com/android/browser/NavigationBarBase.java
@@ -21,7 +21,6 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.speech.RecognizerResultsIntent;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
@@ -35,8 +34,6 @@
 
 import com.android.browser.UrlInputView.UrlInputListener;
 
-import java.util.List;
-
 public class NavigationBarBase extends LinearLayout implements
         OnClickListener, UrlInputListener, OnFocusChangeListener,
         TextWatcher {
@@ -129,7 +126,10 @@
     }
 
     void stopEditingUrl() {
-        mUrlInput.clearFocus();
+        WebView currentTopWebView = mUiController.getCurrentTopWebView();
+        if (currentTopWebView != null) {
+            currentTopWebView.requestFocus();
+        }
     }
 
     void setDisplayTitle(String title) {
@@ -156,10 +156,7 @@
      */
     @Override
     public void onAction(String text, String extra, String source) {
-        WebView currentTopWebView = mUiController.getCurrentTopWebView();
-        if (currentTopWebView != null) {
-            currentTopWebView.requestFocus();
-        }
+        stopEditingUrl();
         if (UrlInputView.TYPED.equals(source)) {
             String url = UrlUtils.smartUrlFilter(text, false);
             Tab t = mBaseUi.getActiveTab();
@@ -220,7 +217,7 @@
     public boolean dispatchKeyEventPreIme(KeyEvent evt) {
         if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
             // catch back key in order to do slightly more cleanup than usual
-            mUrlInput.clearFocus();
+            stopEditingUrl();
             return true;
         }
         return super.dispatchKeyEventPreIme(evt);
@@ -260,6 +257,11 @@
     public void onTabDataChanged(Tab tab) {
     }
 
+    public void onVoiceResult(String s) {
+        startEditingUrl(true, true);
+        onCopySuggestion(s);
+    }
+
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
 
@@ -268,4 +270,5 @@
 
     @Override
     public void afterTextChanged(Editable s) { }
+
 }
diff --git a/src/com/android/browser/NavigationBarPhone.java b/src/com/android/browser/NavigationBarPhone.java
index 2517d62..c3930d3 100644
--- a/src/com/android/browser/NavigationBarPhone.java
+++ b/src/com/android/browser/NavigationBarPhone.java
@@ -38,6 +38,7 @@
     private ImageView mStopButton;
     private ImageView mMagnify;
     private ImageView mClearButton;
+    private ImageView mVoiceButton;
     private Drawable mStopDrawable;
     private Drawable mRefreshDrawable;
     private String mStopDescription;
@@ -71,6 +72,8 @@
         mStopButton.setOnClickListener(this);
         mClearButton = (ImageView) findViewById(R.id.clear);
         mClearButton.setOnClickListener(this);
+        mVoiceButton = (ImageView) findViewById(R.id.voice);
+        mVoiceButton.setOnClickListener(this);
         mMagnify = (ImageView) findViewById(R.id.magnify);
         mTabSwitcher = findViewById(R.id.tab_switcher);
         mTabSwitcher.setOnClickListener(this);
@@ -154,6 +157,8 @@
             mUrlInput.setText("");
         } else if (mComboIcon == v) {
             mUiController.showPageInfo();
+        } else if (mVoiceButton == v) {
+            mUiController.startVoiceRecognizer();
         } else {
             super.onClick(v);
         }
@@ -215,6 +220,7 @@
             mComboIcon.setVisibility(View.VISIBLE);
             mStopButton.setVisibility(View.GONE);
             mClearButton.setVisibility(View.GONE);
+            mVoiceButton.setVisibility(View.GONE);
             mMagnify.setVisibility(View.GONE);
             mTabSwitcher.setVisibility(View.VISIBLE);
             mTitleContainer.setBackgroundDrawable(null);
@@ -224,6 +230,7 @@
             mComboIcon.setVisibility(View.GONE);
             mStopButton.setVisibility(View.VISIBLE);
             mClearButton.setVisibility(View.GONE);
+            mVoiceButton.setVisibility(View.VISIBLE);
             mMagnify.setVisibility(View.GONE);
             mTabSwitcher.setVisibility(View.GONE);
             mMore.setVisibility(View.GONE);
@@ -233,6 +240,7 @@
             mComboIcon.setVisibility(View.GONE);
             mStopButton.setVisibility(View.GONE);
             mClearButton.setVisibility(View.VISIBLE);
+            mVoiceButton.setVisibility(View.GONE);
             mMagnify.setVisibility(View.VISIBLE);
             mTabSwitcher.setVisibility(View.GONE);
             mMore.setVisibility(View.GONE);
diff --git a/src/com/android/browser/NavigationBarTablet.java b/src/com/android/browser/NavigationBarTablet.java
index 426174b..79c8de6 100644
--- a/src/com/android/browser/NavigationBarTablet.java
+++ b/src/com/android/browser/NavigationBarTablet.java
@@ -32,10 +32,9 @@
 import android.widget.ImageView;
 
 import com.android.browser.UI.ComboViews;
+import com.android.browser.UrlInputView.StateListener;
 
-import java.util.List;
-
-public class NavigationBarTablet extends NavigationBarBase {
+public class NavigationBarTablet extends NavigationBarBase implements StateListener {
 
     private Drawable mStopDrawable;
     private Drawable mReloadDrawable;
@@ -51,6 +50,7 @@
     private ImageView mStopButton;
     private View mAllButton;
     private View mClearButton;
+    private View mVoiceButton;
     private View mNavButtons;
     private Drawable mFocusDrawable;
     private Drawable mUnfocusDrawable;
@@ -99,6 +99,7 @@
         mStopButton = (ImageView) findViewById(R.id.stop);
         mSearchButton = (ImageView) findViewById(R.id.search);
         mClearButton = findViewById(R.id.clear);
+        mVoiceButton = findViewById(R.id.voice);
         mUrlContainer = findViewById(R.id.urlbar_focused);
         mBackButton.setOnClickListener(this);
         mForwardButton.setOnClickListener(this);
@@ -107,7 +108,9 @@
         mStopButton.setOnClickListener(this);
         mSearchButton.setOnClickListener(this);
         mClearButton.setOnClickListener(this);
+        mVoiceButton.setOnClickListener(this);
         mUrlInput.setContainer(mUrlContainer);
+        mUrlInput.setStateListener(this);
     }
 
     public void onConfigurationChanged(Configuration config) {
@@ -176,6 +179,8 @@
             stopOrRefresh();
         } else if (mClearButton == v) {
             clearOrClose();
+        } else if (mVoiceButton == v) {
+            mUiController.startVoiceRecognizer();
         } else {
             super.onClick(v);
         }
@@ -217,14 +222,12 @@
             }
             mSearchButton.setVisibility(View.GONE);
             mStar.setVisibility(View.GONE);
-            mClearButton.setVisibility(View.VISIBLE);
             mUrlIcon.setImageResource(R.drawable.ic_search_holo_dark);
         } else {
             if (mHideNavButtons) {
                 showNavButtons();
             }
             showHideStar(mUiController.getCurrentTab());
-            mClearButton.setVisibility(View.GONE);
             if (mTitleBar.useQuickControls()) {
                 mSearchButton.setVisibility(View.GONE);
             } else {
@@ -289,6 +292,7 @@
             mAnimation.cancel();
         }
         mNavButtons.setVisibility(View.VISIBLE);
+        mNavButtons.setTranslationX(0);
         if (!mBaseUi.blockFocusAnimations()) {
             int awidth = mNavButtons.getMeasuredWidth();
             Animator anim1 = ObjectAnimator.ofFloat(mNavButtons,
@@ -316,4 +320,23 @@
         }
     }
 
+    @Override
+    public void onStateChanged(int state) {
+        switch(state) {
+        case STATE_NORMAL:
+            mClearButton.setVisibility(View.GONE);
+            mVoiceButton.setVisibility(View.GONE);
+
+            break;
+        case STATE_HIGHLIGHTED:
+            mClearButton.setVisibility(View.GONE);
+            mVoiceButton.setVisibility(View.VISIBLE);
+            break;
+        case STATE_EDITED:
+            mClearButton.setVisibility(View.VISIBLE);
+            mVoiceButton.setVisibility(View.GONE);
+            break;
+        }
+    }
+
 }
diff --git a/src/com/android/browser/UI.java b/src/com/android/browser/UI.java
index 96f6640..677c3d3 100644
--- a/src/com/android/browser/UI.java
+++ b/src/com/android/browser/UI.java
@@ -148,4 +148,5 @@
 
     boolean blockFocusAnimations();
 
+    void onVoiceResult(String result);
 }
diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java
index b3d4631..d5dfa3e 100644
--- a/src/com/android/browser/UiController.java
+++ b/src/com/android/browser/UiController.java
@@ -107,4 +107,8 @@
 
     BrowserSettings getSettings();
 
+    boolean supportsVoice();
+
+    void startVoiceRecognizer();
+
 }