summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormariakhomenko <mariakhomenko@chromium.org>2015-01-13 13:31:54 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-13 21:33:40 +0000
commit523d40e3b328ed3d3d16a9c6fb3bd9a9d2691956 (patch)
tree51b486610b8ddbd36f60d5f4cc9710914e1fc189
parent83fc6907e8de0362881e4bcdafd4a2186a008aee (diff)
downloadchromium_src-523d40e3b328ed3d3d16a9c6fb3bd9a9d2691956.zip
chromium_src-523d40e3b328ed3d3d16a9c6fb3bd9a9d2691956.tar.gz
chromium_src-523d40e3b328ed3d3d16a9c6fb3bd9a9d2691956.tar.bz2
Upstream parts of omnibox.
Upstreams parts of AutocompleteController dealing with voice suggestions. Upstreams VoiceSuggestionProvider and VoiceSuggestionProviderTest. BUG=428863 Review URL: https://codereview.chromium.org/789103011 Cr-Commit-Position: refs/heads/master@{#311328}
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteController.java36
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProvider.java198
-rw-r--r--chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProviderTest.java404
3 files changed, 637 insertions, 1 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteController.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteController.java
index ed43b69..b9c73de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteController.java
@@ -4,10 +4,12 @@
package org.chromium.chrome.browser.omnibox;
+import android.os.Bundle;
import android.text.TextUtils;
import org.chromium.base.CalledByNative;
import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.omnibox.VoiceSuggestionProvider.VoiceResult;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.content_public.browser.WebContents;
@@ -18,9 +20,17 @@ import java.util.List;
* Bridge to the native AutocompleteControllerAndroid.
*/
public class AutocompleteController {
+ // Maximum number of search/history suggestions to show.
+ private static final int MAX_DEFAULT_SUGGESTION_COUNT = 5;
+
+ // Maximum number of voice suggestions to show.
+ private static final int MAX_VOICE_SUGGESTION_COUNT = 3;
+
private long mNativeAutocompleteControllerAndroid;
private long mCurrentNativeAutocompleteResult;
private final OnSuggestionsReceivedListener mListener;
+ private final VoiceSuggestionProvider mVoiceSuggestionProvider = new VoiceSuggestionProvider();
+
/**
* Listener for receiving OmniboxSuggestions.
@@ -144,6 +154,7 @@ public class AutocompleteController {
* @param clear Whether to clear the most recent autocomplete results.
*/
public void stop(boolean clear) {
+ if (clear) mVoiceSuggestionProvider.clearVoiceSearchResults();
mCurrentNativeAutocompleteResult = 0;
if (mNativeAutocompleteControllerAndroid != 0) {
nativeStop(mNativeAutocompleteControllerAndroid, clear);
@@ -183,6 +194,15 @@ public class AutocompleteController {
List<OmniboxSuggestion> suggestions,
String inlineAutocompleteText,
long currentNativeAutocompleteResult) {
+ if (suggestions.size() > MAX_DEFAULT_SUGGESTION_COUNT) {
+ // Trim to the default amount of normal suggestions we can have.
+ suggestions.subList(MAX_DEFAULT_SUGGESTION_COUNT, suggestions.size()).clear();
+ }
+
+ // Run through new providers to get an updated list of suggestions.
+ suggestions = mVoiceSuggestionProvider.addVoiceSuggestions(
+ suggestions, MAX_VOICE_SUGGESTION_COUNT);
+
mCurrentNativeAutocompleteResult = currentNativeAutocompleteResult;
// Notify callbacks of suggestions.
@@ -207,14 +227,28 @@ public class AutocompleteController {
* modifying text in the omnibox and selecting a suggestion.
* @param webContents The web contents for the tab where the selected suggestion will be shown.
*/
- protected void onSuggestionSelected(int selectedIndex, OmniboxSuggestion.Type type,
+ public void onSuggestionSelected(int selectedIndex, OmniboxSuggestion.Type type,
String currentPageUrl, boolean isQueryInOmnibox, boolean focusedFromFakebox,
long elapsedTimeSinceModified, WebContents webContents) {
+ // Don't natively log voice suggestion results as we add them in Java.
+ if (type == OmniboxSuggestion.Type.VOICE_SUGGEST) return;
nativeOnSuggestionSelected(mNativeAutocompleteControllerAndroid, selectedIndex,
currentPageUrl, isQueryInOmnibox, focusedFromFakebox, elapsedTimeSinceModified,
webContents);
}
+ /**
+ * Pass the autocomplete controller a {@link Bundle} representing the results of a voice
+ * recognition.
+ * @param data A {@link Bundle} containing the results of a voice recognition.
+ * @return The top voice match if one exists, {@code null} otherwise.
+ */
+ public VoiceResult onVoiceResults(Bundle data) {
+ mVoiceSuggestionProvider.setVoiceResultsFromIntentBundle(data);
+ List<VoiceResult> results = mVoiceSuggestionProvider.getResults();
+ return (results != null && results.size() > 0) ? results.get(0) : null;
+ }
+
@CalledByNative
private static List<OmniboxSuggestion> createOmniboxSuggestionList(int size) {
return new ArrayList<OmniboxSuggestion>(size);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProvider.java
new file mode 100644
index 0000000..21c7ceb
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProvider.java
@@ -0,0 +1,198 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox;
+
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.search_engines.TemplateUrlService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A search provider that processes and stores voice recognition results and makes them available
+ * in the omnibox results. The voice results are added to the end of the omnibox results.
+ */
+public class VoiceSuggestionProvider {
+ private static final float CONFIDENCE_THRESHOLD_SHOW = 0.3f;
+ private static final float CONFIDENCE_THRESHOLD_HIDE_ALTS = 0.8f;
+
+ private final List<VoiceResult> mResults = new ArrayList<VoiceResult>();
+
+ private final float mConfidenceThresholdShow;
+ private final float mConfidenceThresholdHideAlts;
+
+ /**
+ * Creates an instance of a {@link VoiceSuggestionProvider} class.
+ */
+ public VoiceSuggestionProvider() {
+ mConfidenceThresholdShow = CONFIDENCE_THRESHOLD_SHOW;
+ mConfidenceThresholdHideAlts = CONFIDENCE_THRESHOLD_HIDE_ALTS;
+ }
+
+ /**
+ * Creates an instance of a {@link VoiceSuggestionProvider} class.
+ * @param confidenceThresholdShow The minimum confidence a result can have to be shown (does not
+ * include the first result). Confidence values are between
+ * 0.0 and 1.0.
+ * @param confidenceThresholdHideAlts The maximum confidence the first result can have before it
+ * will no longer show alternates. Confidence values are
+ * between 0.0 and 1.0.
+ */
+ @VisibleForTesting
+ protected VoiceSuggestionProvider(float confidenceThresholdShow,
+ float confidenceThresholdHideAlts) {
+ mConfidenceThresholdShow = confidenceThresholdShow;
+ mConfidenceThresholdHideAlts = confidenceThresholdHideAlts;
+ }
+
+ /**
+ * Clears the current voice search results.
+ */
+ public void clearVoiceSearchResults() {
+ mResults.clear();
+ }
+
+ /**
+ * @return The current voice search results. This could be {@code null} if no results are
+ * currently present.
+ */
+ public List<VoiceResult> getResults() {
+ return Collections.unmodifiableList(mResults);
+ }
+
+ /**
+ * Takes and processes the results from a recognition action. It parses the confidence and
+ * string values and stores the processed results here so they are made available to the
+ * {@link AutocompleteController} and show up in the omnibox results. This method does not
+ * reorder the voice results that come back from the recognizer.
+ * @param extras The {@link Bundle} that contains the recognition results from a
+ * {@link RecognizerIntent#ACTION_RECOGNIZE_SPEECH} action.
+ */
+ public void setVoiceResultsFromIntentBundle(Bundle extras) {
+ clearVoiceSearchResults();
+
+ if (extras == null) return;
+
+ ArrayList<String> strings = extras.getStringArrayList(
+ RecognizerIntent.EXTRA_RESULTS);
+ float[] confidences = extras.getFloatArray(
+ RecognizerIntent.EXTRA_CONFIDENCE_SCORES);
+
+ if (strings == null || confidences == null) return;
+
+ assert (strings.size() == confidences.length);
+ if (strings.size() != confidences.length) return;
+
+ for (int i = 0; i < strings.size(); ++i) {
+ // Remove any spaces in the voice search match when determining whether it
+ // appears to be a URL. This is to prevent cases like (
+ // "tech crunch.com" and "www. engadget .com" from not appearing like URLs)
+ // from not navigating to the URL.
+ // If the string appears to be a URL, then use it instead of the string returned from
+ // the voice engine.
+ String culledString = strings.get(i).replaceAll(" ", "");
+ String url = AutocompleteController.nativeQualifyPartialURLQuery(culledString);
+ mResults.add(new VoiceResult(
+ url == null ? strings.get(i) : culledString, confidences[i]));
+ }
+ }
+
+ /**
+ * Adds the currently stored voice recognition results to the current list of
+ * {@link OmniboxSuggestion}s passed in. Returns the new list to the caller.
+ * @param suggestions The current list of {@link OmniboxSuggestion}s.
+ * @param maxVoiceResults The maximum number of voice results that should be added.
+ * @return A new list of {@link OmniboxSuggestion}s, which can include voice results.
+ */
+ public List<OmniboxSuggestion> addVoiceSuggestions(
+ List<OmniboxSuggestion> suggestions, int maxVoiceResults) {
+ if (mResults.size() == 0 || maxVoiceResults == 0) return suggestions;
+
+ List<OmniboxSuggestion> newSuggestions = new ArrayList<OmniboxSuggestion>();
+ if (suggestions != null && suggestions.size() > 0) {
+ newSuggestions.addAll(suggestions);
+ }
+
+ VoiceResult firstResult = mResults.get(0);
+ addVoiceResultToOmniboxSuggestions(newSuggestions, firstResult, 0);
+
+ final int suggestionLength = suggestions != null ? suggestions.size() : 0;
+ if (firstResult.getConfidence() < mConfidenceThresholdHideAlts) {
+ for (int i = 1; i < mResults.size()
+ && newSuggestions.size() < suggestionLength + maxVoiceResults; ++i) {
+ addVoiceResultToOmniboxSuggestions(newSuggestions, mResults.get(i),
+ mConfidenceThresholdShow);
+ }
+ }
+
+ return newSuggestions;
+ }
+
+ private void addVoiceResultToOmniboxSuggestions(List<OmniboxSuggestion> suggestions,
+ VoiceResult result, float confidenceThreshold) {
+ if (doesVoiceResultHaveMatch(suggestions, result)) return;
+ if (result.getConfidence() < confidenceThreshold && result.getConfidence() > 0) return;
+ String voiceUrl = TemplateUrlService.getInstance().getUrlForVoiceSearchQuery(
+ result.getMatch());
+ suggestions.add(new OmniboxSuggestion(
+ OmniboxSuggestion.Type.VOICE_SUGGEST.nativeType(),
+ 0,
+ 1,
+ result.getMatch(),
+ null,
+ null,
+ null,
+ null,
+ voiceUrl,
+ voiceUrl,
+ false,
+ false));
+ }
+
+ private boolean doesVoiceResultHaveMatch(List<OmniboxSuggestion> suggestions,
+ VoiceResult result) {
+ for (OmniboxSuggestion suggestion : suggestions) {
+ if (suggestion.getDisplayText().equals(result.getMatch())) return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * A storage class that holds voice recognition string matches and confidence scores.
+ */
+ public static class VoiceResult {
+ private final String mMatch;
+ private final float mConfidence;
+
+ /**
+ * Creates an instance of a VoiceResult.
+ * @param match The text match from the voice recognition.
+ * @param confidence The confidence value of the recognition that should go from 0.0 to 1.0.
+ */
+ public VoiceResult(String match, float confidence) {
+ mMatch = match;
+ mConfidence = confidence;
+ }
+
+ /**
+ * @return The text match from the voice recognition.
+ */
+ public String getMatch() {
+ return mMatch;
+ }
+
+ /**
+ * @return The confidence value of the recognition that should go from 0.0 to 1.0.
+ */
+ public float getConfidence() {
+ return mConfidence;
+ }
+ }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProviderTest.java
new file mode 100644
index 0000000..e5cc217
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/VoiceSuggestionProviderTest.java
@@ -0,0 +1,404 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.omnibox;
+
+import android.os.Bundle;
+import android.speech.RecognizerIntent;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.omnibox.VoiceSuggestionProvider.VoiceResult;
+import org.chromium.chrome.shell.ChromeShellTestBase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test the {@link VoiceSuggestionProvider} class through simulating omnibox results and voice
+ * recognition result bundles.
+ */
+public class VoiceSuggestionProviderTest extends ChromeShellTestBase {
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ launchChromeShellWithBlankPage();
+ assertTrue(waitForActiveShellToBeDoneLoading());
+ }
+
+ private static OmniboxSuggestion createDummySuggestion(String text) {
+ return new OmniboxSuggestion(OmniboxSuggestion.Type.SEARCH_SUGGEST.nativeType(),
+ 0,
+ 1,
+ text,
+ null,
+ null,
+ null,
+ "",
+ "http://www.google.com",
+ "google.com",
+ false,
+ false);
+ }
+
+ private static List<OmniboxSuggestion> createDummySuggestions(String... texts) {
+ List<OmniboxSuggestion> suggestions = new ArrayList<OmniboxSuggestion>(texts.length);
+ for (int i = 0; i < texts.length; ++i) {
+ suggestions.add(createDummySuggestion(texts[i]));
+ }
+
+ return suggestions;
+ }
+
+ private static Bundle createDummyBundle(String[] texts, float[] confidences) {
+ Bundle b = new Bundle();
+
+ b.putStringArrayList(RecognizerIntent.EXTRA_RESULTS, new ArrayList<String>(
+ Arrays.asList(texts)));
+ b.putFloatArray(RecognizerIntent.EXTRA_CONFIDENCE_SCORES, confidences);
+
+ return b;
+ }
+
+ private static void assertVoiceResultsAreEqual(List<VoiceResult> results, String[] texts,
+ float[] confidences) {
+ assertTrue("Invalid array sizes", results.size() == texts.length
+ && texts.length == confidences.length);
+
+ for (int i = 0; i < texts.length; ++i) {
+ VoiceResult result = results.get(i);
+ assertEquals("Match text is not equal", texts[i], result.getMatch());
+ assertEquals("Confidence is not equal", confidences[i], result.getConfidence());
+ }
+ }
+
+ private static boolean assertSuggestionMatchesVoiceResult(OmniboxSuggestion a, VoiceResult b) {
+ return a.getType() == OmniboxSuggestion.Type.VOICE_SUGGEST && !a.isStarred()
+ && TextUtils.equals(a.getDisplayText(), b.getMatch());
+ }
+
+ private void assertArrayStartsWith(List<OmniboxSuggestion> a, List<OmniboxSuggestion> b) {
+ assertTrue((a != null && b != null) || (a == null && b == null));
+ if (a == null || b == null) return;
+
+ assertTrue(a.size() >= b.size());
+ for (int i = 0; i < b.size(); ++i) {
+ assertEquals("The OmniboxSuggestion entries are not the same.", a.get(i), b.get(i));
+ }
+ }
+
+ private void assertArrayEndsWith(List<OmniboxSuggestion> a, List<VoiceResult> b,
+ int expectedResultCount) {
+ assertTrue((a != null && b != null) || (a == null && b == null));
+ if (a == null || b == null) return;
+
+ expectedResultCount = Math.min(expectedResultCount, b.size());
+ assertTrue(a.size() >= expectedResultCount);
+ for (int i = 0; i < expectedResultCount; ++i) {
+ assertTrue("The OmniboxSuggestion entry does not match the VoiceResult",
+ assertSuggestionMatchesVoiceResult(a.get(a.size() - expectedResultCount + i),
+ b.get(i)));
+ }
+ }
+
+ private boolean isVoiceResultInSuggestions(List<OmniboxSuggestion> suggestions,
+ VoiceResult result) {
+ for (OmniboxSuggestion suggestion : suggestions) {
+ if (assertSuggestionMatchesVoiceResult(suggestion, result)) return true;
+ }
+
+ return false;
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testParseEmptyBundle() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ provider.setVoiceResultsFromIntentBundle(new Bundle());
+
+ assertNotNull("Results is null", provider.getResults());
+ assertEquals("SuggestionProvider added invalid results", 0,
+ provider.getResults().size());
+
+ provider.addVoiceSuggestions(null, 3);
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testParseBundle() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 0.8f, 1.0f, 1.0f };
+
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ assertVoiceResultsAreEqual(provider.getResults(), texts, confidences);
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testNoSuggestions() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+ List<OmniboxSuggestion> suggestions =
+ createDummySuggestions("a", "b", "c");
+ List<OmniboxSuggestion> updatedSuggestions =
+ provider.addVoiceSuggestions(suggestions, 10);
+
+ android.test.MoreAsserts.assertEquals(
+ suggestions.toArray(), updatedSuggestions.toArray());
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testClearVoiceResults() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 0.99f, 0.98f };
+
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ assertNotNull(provider.getResults());
+ assertEquals("Invalid number of results", texts.length,
+ provider.getResults().size());
+
+ provider.clearVoiceSearchResults();
+
+ assertEquals(0, provider.getResults().size());
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testAddToEmtpyResultsCase() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 1.0f, 1.0f };
+
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+ assertVoiceResultsAreEqual(provider.getResults(), texts, confidences);
+ List<OmniboxSuggestion> suggestions =
+ provider.addVoiceSuggestions(null, texts.length);
+ assertArrayEndsWith(suggestions, provider.getResults(), texts.length);
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testAddToEmptyOverflowCase() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 1.0f, 1.0f };
+
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+ assertVoiceResultsAreEqual(provider.getResults(), texts, confidences);
+
+ List<OmniboxSuggestion> suggestions = provider.addVoiceSuggestions(null, 2);
+ assertArrayEndsWith(suggestions, provider.getResults(), 2);
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testAddToResultsCase() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 1.0f, 1.0f };
+
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ List<OmniboxSuggestion> suggestions =
+ createDummySuggestions("oa", "ob", "oc");
+ List<OmniboxSuggestion> updatedSuggestions =
+ provider.addVoiceSuggestions(suggestions, texts.length);
+
+ assertArrayStartsWith(updatedSuggestions, suggestions);
+ assertArrayEndsWith(updatedSuggestions, provider.getResults(), texts.length);
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testAddToResultsOverflowCase() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 1.0f, 1.0f };
+
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ List<OmniboxSuggestion> suggestions =
+ createDummySuggestions("oa", "ob", "oc");
+ List<OmniboxSuggestion> updatedSuggestions =
+ provider.addVoiceSuggestions(suggestions, 2);
+
+ assertArrayStartsWith(updatedSuggestions, suggestions);
+ assertArrayEndsWith(updatedSuggestions, provider.getResults(), 2);
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testAddDuplicateToResultsCase() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.0f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 1.0f, 1.0f };
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ List<OmniboxSuggestion> suggestions =
+ createDummySuggestions("oa", "b", "oc");
+ List<OmniboxSuggestion> updatedSuggestions =
+ provider.addVoiceSuggestions(suggestions, texts.length);
+
+ assertEquals(provider.getResults().get(0).getMatch(), texts[0]);
+ assertTrue("Result 'a' was not found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(0)));
+ assertEquals(provider.getResults().get(1).getMatch(), texts[1]);
+ assertFalse("Result 'b' was found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(1)));
+ assertEquals(provider.getResults().get(2).getMatch(), texts[2]);
+ assertTrue("Result 'c' was not found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(2)));
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testConfidenceThresholdHideLowConfidence() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.5f, 1.1f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 1.0f, 0.6f, 0.3f };
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ List<OmniboxSuggestion> suggestions =
+ createDummySuggestions("oa", "ob", "oc");
+ List<OmniboxSuggestion> updatedSuggestions =
+ provider.addVoiceSuggestions(suggestions, texts.length);
+
+ assertEquals(provider.getResults().get(0).getMatch(), texts[0]);
+ assertTrue("Result 'a' was not found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(0)));
+ assertEquals(provider.getResults().get(1).getMatch(), texts[1]);
+ assertTrue("Result 'b' was not found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(1)));
+ assertEquals(provider.getResults().get(2).getMatch(), texts[2]);
+ assertFalse("Result 'c' was found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(2)));
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testConfidenceThresholdHideAlts() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider(0.5f, 0.5f);
+
+ String[] texts = new String[] { "a", "b", "c" };
+ float[] confidences = new float[] { 0.8f, 1.0f, 1.0f };
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ List<OmniboxSuggestion> suggestions =
+ createDummySuggestions("oa", "ob", "oc");
+ List<OmniboxSuggestion> updatedSuggestions =
+ provider.addVoiceSuggestions(suggestions, texts.length);
+
+ assertEquals(provider.getResults().get(0).getMatch(), texts[0]);
+ assertTrue("Result 'a' was not found (First entry. Must be shown).",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(0)));
+ assertEquals(provider.getResults().get(1).getMatch(), texts[1]);
+ assertFalse("Result 'b' was found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(1)));
+ assertEquals(provider.getResults().get(2).getMatch(), texts[2]);
+ assertFalse("Result 'c' was found.",
+ isVoiceResultInSuggestions(updatedSuggestions,
+ provider.getResults().get(2)));
+ }
+ });
+ }
+
+ @SmallTest
+ @Feature({"Omnibox"})
+ public void testVoiceResponseURLConversion() {
+ ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ @Override
+ public void run() {
+ VoiceSuggestionProvider provider = new VoiceSuggestionProvider();
+
+ String[] texts =
+ new String[] { "a", "www. b .co .uk", "engadget .com", "www.google.com" };
+ float[] confidences = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
+ provider.setVoiceResultsFromIntentBundle(createDummyBundle(texts, confidences));
+
+ assertVoiceResultsAreEqual(
+ provider.getResults(),
+ new String[] {"a", "www.b.co.uk", "engadget.com", "www.google.com"},
+ new float[] {1.0f, 1.0f, 1.0f, 1.0f});
+ }
+ });
+ }
+}