diff options
author | mariakhomenko <mariakhomenko@chromium.org> | 2015-01-13 13:31:54 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-13 21:33:40 +0000 |
commit | 523d40e3b328ed3d3d16a9c6fb3bd9a9d2691956 (patch) | |
tree | 51b486610b8ddbd36f60d5f4cc9710914e1fc189 | |
parent | 83fc6907e8de0362881e4bcdafd4a2186a008aee (diff) | |
download | chromium_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}
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}); + } + }); + } +} |