13e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/* 23e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project 33e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 43e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 53e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * you may not use this file except in compliance with the License. 63e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * You may obtain a copy of the License at 73e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 83e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 93e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * See the License for the specific language governing permissions and 143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * limitations under the License. 153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpackage com.android.quicksearchbox; 183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 193e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.Activity; 203e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.SearchManager; 213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.content.Intent; 22fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringertimport android.net.Uri; 233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.os.Bundle; 2411234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringertimport android.os.Debug; 254ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringertimport android.os.Handler; 263e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.text.TextUtils; 273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.util.Log; 283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.Menu; 293e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.view.View; 30ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood 31ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwoodimport com.android.common.Search; 32ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwoodimport com.android.quicksearchbox.ui.SearchActivityView; 33ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwoodimport com.android.quicksearchbox.ui.SuggestionClickListener; 34ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwoodimport com.android.quicksearchbox.ui.SuggestionsAdapter; 35ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwoodimport com.google.common.annotations.VisibleForTesting; 36ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwoodimport com.google.common.base.CharMatcher; 373e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3811234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringertimport java.io.File; 39ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/** 413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * The main activity for Quick Search Box. Shows the search UI. 423e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * 433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */ 443e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpublic class SearchActivity extends Activity { 453e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 46754cb6b769c5955fc707a6c5ab6689b64df102b3Mathew Inwood private static final boolean DBG = false; 470484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert private static final String TAG = "QSB.SearchActivity"; 483e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 49fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert private static final String SCHEME_CORPUS = "qsb.corpus"; 50fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 5148ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert private static final String INTENT_EXTRA_TRACE_START_UP = "trace_start_up"; 5248ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert 539ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Keys for the saved instance state. 54839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert private static final String INSTANCE_KEY_QUERY = "query"; 55713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 5671f9f8ccd3c12d7d48e2fee4c55cd57e1970b797Bjorn Bringert private static final String ACTIVITY_HELP_CONTEXT = "search"; 5771f9f8ccd3c12d7d48e2fee4c55cd57e1970b797Bjorn Bringert 5848ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert private boolean mTraceStartUp; 59f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert // Measures time from for last onCreate()/onNewIntent() call. 60f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert private LatencyTracker mStartLatencyTracker; 6198cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood // Measures time spent inside onCreate() 6298cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood private LatencyTracker mOnCreateTracker; 6398cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood private int mOnCreateLatency; 64ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // Whether QSB is starting. True between the calls to onCreate()/onNewIntent() and onResume(). 65ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mStarting; 66ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // True if the user has taken some action, e.g. launching a search, voice search, 67ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert // or suggestions, since QSB was last started. 68ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private boolean mTookAction; 69ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 707010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert private SearchActivityView mSearchActivityView; 71185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 72ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood private Source mSource; 7321bff9bbf4286907b01d3153bff2fbd6b5ec5df8Bjorn Bringert 742617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert private Bundle mAppSearchData; 753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 76d6b9bd42f22582a8ccec657bd6d715465de98ec9Mathew Inwood private final Handler mHandler = new Handler(); 77d6b9bd42f22582a8ccec657bd6d715465de98ec9Mathew Inwood private final Runnable mUpdateSuggestionsTask = new Runnable() { 78ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 794ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert public void run() { 807f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert updateSuggestions(); 814ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert } 824ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert }; 834ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert 84d6b9bd42f22582a8ccec657bd6d715465de98ec9Mathew Inwood private final Runnable mShowInputMethodTask = new Runnable() { 85ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 86d98911178013162737fbba74387b51d2a08b0493Amith Yamasani public void run() { 877010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.showInputMethodForQuery(); 88d98911178013162737fbba74387b51d2a08b0493Amith Yamasani } 89d98911178013162737fbba74387b51d2a08b0493Amith Yamasani }; 90d98911178013162737fbba74387b51d2a08b0493Amith Yamasani 912607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood private OnDestroyListener mDestroyListener; 922607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood 933e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert /** Called when the activity is first created. */ 943e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 953e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert public void onCreate(Bundle savedInstanceState) { 9648ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert mTraceStartUp = getIntent().hasExtra(INTENT_EXTRA_TRACE_START_UP); 9748ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert if (mTraceStartUp) { 9848ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert String traceFile = new File(getDir("traces", 0), "qsb-start.trace").getAbsolutePath(); 9948ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert Log.i(TAG, "Writing start-up trace to " + traceFile); 10048ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert Debug.startMethodTracing(traceFile); 10148ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert } 102ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1033e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onCreate()"); 1043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onCreate(savedInstanceState); 105713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 106c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath // This forces the HTTP request to check the users domain to be 107c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath // sent as early as possible. 108c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath QsbApplication.get(this).getSearchBaseUrlHelper(); 109c953ef06f0fc1fb4157fe67aa145cf702ee204d0Narayan Kamath 110ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood mSource = QsbApplication.get(this).getGoogleSource(); 111ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood 1125880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert mSearchActivityView = setupContentView(); 113aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood 114f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood if (getConfig().showScrollingResults()) { 1157a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood mSearchActivityView.setMaxPromotedResults(getConfig().getMaxPromotedResults()); 116f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood } else { 117f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood mSearchActivityView.limitResultsToViewHeight(); 118f5a8912d5da80378d38b667eba4aaa0555aea7bdMathew Inwood } 119848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani 1207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.setSearchClickListener(new SearchActivityView.SearchClickListener() { 121ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 1227010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public boolean onSearchClicked(int method) { 1237010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return SearchActivity.this.onSearchClicked(method); 1247010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1257010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert }); 1262617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 1277010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.setQueryListener(new SearchActivityView.QueryListener() { 128ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 1297010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onQueryChanged() { 1307010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert updateSuggestionsBuffered(); 1317010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1327010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert }); 133782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 1347010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.setSuggestionClickListener(new ClickHandler()); 1357be9c66fdc2e4df2e998d79a11bcf737ffddc2dcBjorn Bringert 1367010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.setVoiceSearchButtonClickListener(new View.OnClickListener() { 137ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 1387010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert public void onClick(View view) { 1397010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert onVoiceSearchClicked(); 1407010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert } 1417010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert }); 1429ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 143e833f84eee7ab575c8d53dec9b133fa5de9c7e6dMathew Inwood View.OnClickListener finishOnClick = new View.OnClickListener() { 144ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 1459e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood public void onClick(View v) { 1469e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood finish(); 1479e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood } 148e833f84eee7ab575c8d53dec9b133fa5de9c7e6dMathew Inwood }; 149e833f84eee7ab575c8d53dec9b133fa5de9c7e6dMathew Inwood mSearchActivityView.setExitClickListener(finishOnClick); 1509e46c057d7f88d2a899e124f96d266c54250bb45Mathew Inwood 1519ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // First get setup from intent 1529ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert Intent intent = getIntent(); 1539ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1549ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Then restore any saved instance state 1559ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert restoreInstanceState(savedInstanceState); 1569ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 157713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // Do this at the end, to avoid updating the list view when setSource() 158713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert // is called. 1597010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.start(); 16021bff9bbf4286907b01d3153bff2fbd6b5ec5df8Bjorn Bringert 16198cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood recordOnCreateDone(); 1629ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 163713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 1645880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert protected SearchActivityView setupContentView() { 1656ae65b29ce9313a4f0624ef825f75151db5ec2feBjorn Bringert setContentView(R.layout.search_activity); 1665880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert return (SearchActivityView) findViewById(R.id.search_activity_view); 1675880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert } 1685880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert 1695880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert protected SearchActivityView getSearchActivityView() { 1705880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert return mSearchActivityView; 1716ae65b29ce9313a4f0624ef825f75151db5ec2feBjorn Bringert } 1726ae65b29ce9313a4f0624ef825f75151db5ec2feBjorn Bringert 1739ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert @Override 1749ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onNewIntent(Intent intent) { 175839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert if (DBG) Log.d(TAG, "onNewIntent()"); 176ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert recordStartTime(); 1779ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setIntent(intent); 1789ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert setupFromIntent(intent); 1799ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert } 1809ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert 181ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private void recordStartTime() { 182f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert mStartLatencyTracker = new LatencyTracker(); 18398cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood mOnCreateTracker = new LatencyTracker(); 184ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mStarting = true; 185ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = false; 186ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 187ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 18898cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood private void recordOnCreateDone() { 18998cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood mOnCreateLatency = mOnCreateTracker.getLatency(); 19098cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood } 19198cbee7f6266509a0805b3fef060f01caaef69e3Mathew Inwood 1929ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void restoreInstanceState(Bundle savedInstanceState) { 1939ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (savedInstanceState == null) return; 194839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert String query = savedInstanceState.getString(INSTANCE_KEY_QUERY); 195839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert setQuery(query, false); 196713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 197713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 198713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert @Override 1999ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert protected void onSaveInstanceState(Bundle outState) { 2009ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert super.onSaveInstanceState(outState); 2019ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // We don't save appSearchData, since we always get the value 2029ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // from the intent and the user can't change it. 203fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 204839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert outState.putString(INSTANCE_KEY_QUERY, getQuery()); 205713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert } 206713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert 207713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert private void setupFromIntent(Intent intent) { 208713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert if (DBG) Log.d(TAG, "setupFromIntent(" + intent.toUri(0) + ")"); 20921bff9bbf4286907b01d3153bff2fbd6b5ec5df8Bjorn Bringert String corpusName = getCorpusNameFromUri(intent.getData()); 2102617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert String query = intent.getStringExtra(SearchManager.QUERY); 2112617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA); 212839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert boolean selectAll = intent.getBooleanExtra(SearchManager.EXTRA_SELECT_QUERY, false); 2132617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 214839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert setQuery(query, selectAll); 215c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert mAppSearchData = appSearchData; 2162617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert 217fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 218fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 21921bff9bbf4286907b01d3153bff2fbd6b5ec5df8Bjorn Bringert private String getCorpusNameFromUri(Uri uri) { 220fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (uri == null) return null; 221fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert if (!SCHEME_CORPUS.equals(uri.getScheme())) return null; 22221bff9bbf4286907b01d3153bff2fbd6b5ec5df8Bjorn Bringert return uri.getAuthority(); 223fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert } 224fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert 2253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert private QsbApplication getQsbApplication() { 22649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert return QsbApplication.get(this); 2273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2294ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert private Config getConfig() { 2304ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert return getQsbApplication().getConfig(); 2314ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert } 2324ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert 23396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert protected SearchSettings getSettings() { 23496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return getQsbApplication().getSettings(); 23596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 23696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 237b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert private SuggestionsProvider getSuggestionsProvider() { 238b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert return getQsbApplication().getSuggestionsProvider(); 23947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert } 24047d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert 241ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert private Logger getLogger() { 242ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert return getQsbApplication().getLogger(); 243ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert } 244ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 2452607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood @VisibleForTesting 2462607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood public void setOnDestroyListener(OnDestroyListener l) { 2472607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood mDestroyListener = l; 2482607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood } 2492607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood 2503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onDestroy() { 2523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "onDestroy()"); 2537010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.destroy(); 2542607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood super.onDestroy(); 2552607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood if (mDestroyListener != null) { 2562607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood mDestroyListener.onDestroyed(); 2572607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood } 2583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2613e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onStop() { 2629ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onStop()"); 263f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert if (!mTookAction) { 264848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani // TODO: This gets logged when starting other activities, e.g. by opening the search 265f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert // settings, or clicking a notification in the status bar. 266aa7d79792baca59eb7afe00ea27abc5176ddd34bMathew Inwood // TODO we should log both sets of suggestions in 2-pane mode 267f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert getLogger().logExit(getCurrentSuggestions(), getQuery().length()); 268f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert } 2699ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert // Close all open suggestion cursors. The query will be redone in onResume() 2703e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert // if we come back to this activity. 2717010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.clearSuggestions(); 2720a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood mSearchActivityView.onStop(); 2733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert super.onStop(); 2743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 2753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 2763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert @Override 2772e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani protected void onPause() { 2782e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani if (DBG) Log.d(TAG, "onPause()"); 2792e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani mSearchActivityView.onPause(); 2802e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani super.onPause(); 2812e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani } 2822e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani 2832e684983c6a20faa209e42f6c63337cfcb34fc71Amith Yamasani @Override 284839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert protected void onRestart() { 285839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert if (DBG) Log.d(TAG, "onRestart()"); 286839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert super.onRestart(); 287839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert } 288839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert 289839a9fd2828f37c9dc8345f93aefa5b8ad2f857fBjorn Bringert @Override 290b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert protected void onResume() { 2919ad03a750a66b26441a19ff54b6057729c145eaeBjorn Bringert if (DBG) Log.d(TAG, "onResume()"); 292b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert super.onResume(); 29311234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert updateSuggestionsBuffered(); 2940a73d81f02118d0343d3f1c9219a8354466f72b3Mathew Inwood mSearchActivityView.onResume(); 29548ced2f683491d07d892ec81f88fe2e26f9207c2Bjorn Bringert if (mTraceStartUp) Debug.stopMethodTracing(); 296b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert } 297b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert 298b32ee8f1b45c65daff18b40c0614cf18843b8c17Bjorn Bringert @Override 29973a375928e0b8f0b2bfa09e4b252cfcbdad4ef84Bjorn Bringert public boolean onPrepareOptionsMenu(Menu menu) { 30073a375928e0b8f0b2bfa09e4b252cfcbdad4ef84Bjorn Bringert // Since the menu items are dynamic, we recreate the menu every time. 30173a375928e0b8f0b2bfa09e4b252cfcbdad4ef84Bjorn Bringert menu.clear(); 30273a375928e0b8f0b2bfa09e4b252cfcbdad4ef84Bjorn Bringert createMenuItems(menu, true); 30396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return true; 30496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 30596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 30673a375928e0b8f0b2bfa09e4b252cfcbdad4ef84Bjorn Bringert public void createMenuItems(Menu menu, boolean showDisabled) { 30771f9f8ccd3c12d7d48e2fee4c55cd57e1970b797Bjorn Bringert getQsbApplication().getHelp().addHelpMenuItem(menu, ACTIVITY_HELP_CONTEXT); 3085eee22a4ec6fc45deb9706ba535039ccae51b90aBjorn Bringert } 3095eee22a4ec6fc45deb9706ba535039ccae51b90aBjorn Bringert 31096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert @Override 311d98911178013162737fbba74387b51d2a08b0493Amith Yamasani public void onWindowFocusChanged(boolean hasFocus) { 312d98911178013162737fbba74387b51d2a08b0493Amith Yamasani super.onWindowFocusChanged(hasFocus); 313d98911178013162737fbba74387b51d2a08b0493Amith Yamasani if (hasFocus) { 314d98911178013162737fbba74387b51d2a08b0493Amith Yamasani // Launch the IME after a bit 315d98911178013162737fbba74387b51d2a08b0493Amith Yamasani mHandler.postDelayed(mShowInputMethodTask, 0); 316d98911178013162737fbba74387b51d2a08b0493Amith Yamasani } 317d98911178013162737fbba74387b51d2a08b0493Amith Yamasani } 318d98911178013162737fbba74387b51d2a08b0493Amith Yamasani 319713194910648268c094fa81b81f40ce2f7e39333Bjorn Bringert protected String getQuery() { 3207010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert return mSearchActivityView.getQuery(); 3213e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3237010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert protected void setQuery(String query, boolean selectAll) { 3247010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.setQuery(query, selectAll); 325e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert } 326e4f5c630a1c9cdf75fe751dc728729c3ecb7ae07Bjorn Bringert 327dd6d9a1a8d559c87f54412eb4e6569ed62193d60Mathew Inwood /** 328dd6d9a1a8d559c87f54412eb4e6569ed62193d60Mathew Inwood * @return true if a search was performed as a result of this click, false otherwise. 329dd6d9a1a8d559c87f54412eb4e6569ed62193d60Mathew Inwood */ 330dd6d9a1a8d559c87f54412eb4e6569ed62193d60Mathew Inwood protected boolean onSearchClicked(int method) { 3313a7125b39b72f7417684c4d3040abeb4a81bd6b3Bjorn Bringert String query = CharMatcher.WHITESPACE.trimAndCollapseFrom(getQuery(), ' '); 3323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Search clicked, query=" + query); 333eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert 334eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert // Don't do empty queries 335dd6d9a1a8d559c87f54412eb4e6569ed62193d60Mathew Inwood if (TextUtils.getTrimmedLength(query) == 0) return false; 336eba26da75665ac3b9a411e74267395f332ff851aBjorn Bringert 337ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 338c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 339c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log search start 340ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood getLogger().logSearch(method, query.length()); 341c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 342c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Start search 343ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood startSearch(mSource, query); 3449d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert return true; 3459d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert } 3469d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert 347ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood protected void startSearch(Source searchSource, String query) { 348ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood Intent intent = searchSource.createSearchIntent(query, mAppSearchData); 34981a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert launchIntent(intent); 3503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 3513e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 3523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert protected void onVoiceSearchClicked() { 3533e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert if (DBG) Log.d(TAG, "Voice Search clicked"); 354c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert 355535931433926d342c6277034cad91143ae28b72dBjorn Bringert mTookAction = true; 356535931433926d342c6277034cad91143ae28b72dBjorn Bringert 357c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log voice search start 358ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood getLogger().logVoiceSearch(); 359ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 360c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Start voice search 361ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood Intent intent = mSource.createVoiceSearchIntent(mAppSearchData); 36281a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert launchIntent(intent); 36381a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert } 36481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert 365ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood protected Source getSearchSource() { 366ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood return mSource; 367014e0d0c0a5102b7cc1c5576a3af25a646731dd0Bjorn Bringert } 368014e0d0c0a5102b7cc1c5576a3af25a646731dd0Bjorn Bringert 369e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert protected SuggestionCursor getCurrentSuggestions() { 370ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood return mSearchActivityView.getSuggestions().getResult(); 371782dd228e78e9294692d639597f96c26283968bbBjorn Bringert } 372782dd228e78e9294692d639597f96c26283968bbBjorn Bringert 3737a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood protected SuggestionPosition getCurrentSuggestions(SuggestionsAdapter<?> adapter, long id) { 3747a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood SuggestionPosition pos = adapter.getSuggestion(id); 3757a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood if (pos == null) { 3767a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood return null; 3777a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood } 3787a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood SuggestionCursor suggestions = pos.getCursor(); 3797a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood int position = pos.getPosition(); 3805f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert if (suggestions == null) { 3815f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert return null; 3825f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert } 3835f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert int count = suggestions.getCount(); 3845f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert if (position < 0 || position >= count) { 3855f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert Log.w(TAG, "Invalid suggestion position " + position + ", count = " + count); 3865f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert return null; 3875f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert } 3885f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert suggestions.moveTo(position); 3897a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood return pos; 3905f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert } 3915f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert 39281a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert protected void launchIntent(Intent intent) { 39313b4f2dc4b339790c2b9b0220be47c8e77fd61eaMathew Inwood if (DBG) Log.d(TAG, "launchIntent " + intent); 39481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert if (intent == null) { 39581a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert return; 39681a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert } 39781a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert try { 39881a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert startActivity(intent); 39981a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert } catch (RuntimeException ex) { 40081a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert // Since the intents for suggestions specified by suggestion providers, 40181a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert // guard against them not being handled, not allowed, etc. 40281a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert Log.e(TAG, "Failed to start " + intent.toUri(0), ex); 40381a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert } 40481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert } 40581a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert 4067a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood private boolean launchSuggestion(SuggestionsAdapter<?> adapter, long id) { 4077a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood SuggestionPosition suggestion = getCurrentSuggestions(adapter, id); 4087a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood if (suggestion == null) return false; 4096f8fc42e68237bfb6f474faff8086d910d2934d5Bjorn Bringert 4107a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood if (DBG) Log.d(TAG, "Launching suggestion " + id); 411ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert mTookAction = true; 412e06b7cbf55301a24cfd7525a91107e3cd2c9f48eBjorn Bringert 413c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Log suggestion click 414ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood getLogger().logSuggestionClick(id, suggestion.getCursor(), 415c020c1844b0fb3a825e8a6fa6ad96288bc432fbcBjorn Bringert Logger.SUGGESTION_CLICK_TYPE_LAUNCH); 416ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert 417c29c9f854db8fa0c85f17cc32bae33dc17c6b127Bjorn Bringert // Launch intent 4187a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood launchSuggestion(suggestion.getCursor(), suggestion.getPosition()); 4199d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert 4209d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert return true; 4219d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert } 4229d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert 4239d731c0bae275ee9b1c87b679820259c18cc68c8Bjorn Bringert protected void launchSuggestion(SuggestionCursor suggestions, int position) { 42481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert suggestions.moveTo(position); 42593bd2e70b8b08da1ec37fd0e990dac05551d2e90Bjorn Bringert Intent intent = SuggestionUtils.getSuggestionIntent(suggestions, mAppSearchData); 42681a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert launchIntent(intent); 4273e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4283e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4297a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood protected void refineSuggestion(SuggestionsAdapter<?> adapter, long id) { 4307a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood if (DBG) Log.d(TAG, "query refine clicked, pos " + id); 4317a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood SuggestionPosition suggestion = getCurrentSuggestions(adapter, id); 4327a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood if (suggestion == null) { 4335f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert return; 4345f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert } 4357a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood String query = suggestion.getSuggestionQuery(); 4365f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert if (TextUtils.isEmpty(query)) { 4375f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert return; 4385f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert } 4395f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert 4405f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert // Log refine click 441ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood getLogger().logSuggestionClick(id, suggestion.getCursor(), 442c020c1844b0fb3a825e8a6fa6ad96288bc432fbcBjorn Bringert Logger.SUGGESTION_CLICK_TYPE_REFINE); 4435f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert 4445f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert // Put query + space in query text view 4455f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert String queryWithSpace = query + ' '; 4465f71d5746ec042ad2e5c1eee8c83514f92534372Bjorn Bringert setQuery(queryWithSpace, false); 447dfc1772caf35942837d83331d787eb10734c37cbBjorn Bringert updateSuggestions(); 4487010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.focusQueryTextView(); 4493e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert } 4503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert 4514ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert private void updateSuggestionsBuffered() { 4527f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "updateSuggestionsBuffered()"); 453d98911178013162737fbba74387b51d2a08b0493Amith Yamasani mHandler.removeCallbacks(mUpdateSuggestionsTask); 4544ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert long delay = getConfig().getTypingUpdateSuggestionsDelayMillis(); 455d98911178013162737fbba74387b51d2a08b0493Amith Yamasani mHandler.postDelayed(mUpdateSuggestionsTask, delay); 4564ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert } 4574ef1338a23b040df2ef180c48ff85e14a9d70906Bjorn Bringert 458b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert private void gotSuggestions(Suggestions suggestions) { 45911234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert if (mStarting) { 46011234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert mStarting = false; 46111234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert String source = getIntent().getStringExtra(Search.SOURCE); 46211234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert int latency = mStartLatencyTracker.getLatency(); 463ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood getLogger().logStart(mOnCreateLatency, latency, source); 464b5560dbe16a8fb3148b0fb24c73836bf2e84dd61Mathew Inwood getQsbApplication().onStartupComplete(); 46511234b9966c6b0e5c17d00e3b973c0d49a8d1f57Bjorn Bringert } 466848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani } 467848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani 468dfc1772caf35942837d83331d787eb10734c37cbBjorn Bringert public void updateSuggestions() { 4697f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "updateSuggestions()"); 4707f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert final String query = CharMatcher.WHITESPACE.trimLeadingFrom(getQuery()); 471ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood updateSuggestions(query, mSource); 4726859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 473b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert 474ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood protected void updateSuggestions(String query, Source source) { 475ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood if (DBG) Log.d(TAG, "updateSuggestions(\"" + query+"\"," + source + ")"); 476b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert Suggestions suggestions = getSuggestionsProvider().getSuggestions( 477ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood query, source); 478b42184f1e6a1b7bb22797ff92cae696753aca770Bjorn Bringert 479b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert // Log start latency if this is the first suggestions update 480b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert gotSuggestions(suggestions); 481b83882b9efa37ec0f20a0f1c85cf5ccc93194aeeBjorn Bringert 4825880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert showSuggestions(suggestions); 4835880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert } 4845880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert 4855880fdc4f6fef3c9b5b95a49a0f23c37c69f89d5Bjorn Bringert protected void showSuggestions(Suggestions suggestions) { 4867010c51b51c97fa43d7b24d2158ecbc1d064e0a6Bjorn Bringert mSearchActivityView.setSuggestions(suggestions); 487185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert } 488185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert 489185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert private class ClickHandler implements SuggestionClickListener { 490848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani 491ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 4927a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood public void onSuggestionClicked(SuggestionsAdapter<?> adapter, long id) { 4937a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood launchSuggestion(adapter, id); 494848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani } 495145693e12b77c193a65b7eaa038a272dd1f48f33Bjorn Bringert 496ecf356c15143ab0583c64682de16d94a57f7dd1cMathew Inwood @Override 4977a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood public void onSuggestionQueryRefineClicked(SuggestionsAdapter<?> adapter, long id) { 4987a0c3a7c6fdabce949b59e0a2c6ec1d44a140c24Mathew Inwood refineSuggestion(adapter, id); 4992617a0177a6088d5aaf381263229bf5a62d2238dBjorn Bringert } 500f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert } 501f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert 5022607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood public interface OnDestroyListener { 5032607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood void onDestroyed(); 5042607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood } 5052607687d72deb8e06329597ab8bffcca9c746153Mathew Inwood 5063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert} 507