SearchSettingsImpl.java revision 96fec862c3d494aebcb4e1d93589a241385a2ba7
196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert/* 296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project 396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * 496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * you may not use this file except in compliance with the License. 696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * You may obtain a copy of the License at 796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * 896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * 1096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 1196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 1296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * See the License for the specific language governing permissions and 1496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * limitations under the License. 1596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 1696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 1796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertpackage com.android.quicksearchbox; 1896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 1996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.app.SearchManager; 2096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.content.Context; 2196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.content.Intent; 2296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.content.SharedPreferences; 2396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.provider.Settings; 2496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.util.Log; 2596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.view.Menu; 2696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.view.MenuInflater; 2796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertimport android.view.MenuItem; 2896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 2996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert/** 3096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Manages user settings. 3196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 3296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringertpublic class SearchSettingsImpl implements SearchSettings { 3396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 3496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final boolean DBG = false; 3596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String TAG = "QSB.SearchSettingsImpl"; 3696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 3796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert // Name of the preferences file used to store search preference 3896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public static final String PREFERENCES_NAME = "SearchSettings"; 3996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 4096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert // Intent action that opens the "Searchable Items" preference 4196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String ACTION_SEARCHABLE_ITEMS = 4296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert "com.android.quicksearchbox.action.SEARCHABLE_ITEMS"; 4396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 4496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String SHOW_WEB_SUGGESTIONS_PREF = "show_web_suggestions"; 4596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 4696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 4796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Preference key used for storing the index of the next voice search hint to show. 4896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 4996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String NEXT_VOICE_SEARCH_HINT_INDEX_PREF = "next_voice_search_hint"; 5096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 5196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 5296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Preference key used to store the time at which the first voice search hint was displayed. 5396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 5496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String FIRST_VOICE_HINT_DISPLAY_TIME = "first_voice_search_hint_time"; 5596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 5696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 5796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Preference key for the version of voice search we last got hints from. 5896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 5996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String LAST_SEEN_VOICE_SEARCH_VERSION = "voice_search_version"; 6096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 6196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 6296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Prefix of per-corpus enable preference 6396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 6496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static final String CORPUS_ENABLED_PREF_PREFIX = "enable_corpus_"; 6596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 6696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private final Context mContext; 6796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 6896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private final Config mConfig; 6996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 7096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public SearchSettingsImpl(Context context, Config config) { 7196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert mContext = context; 7296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert mConfig = config; 7396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 7496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 7596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert protected Context getContext() { 7696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return mContext; 7796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 7896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 7996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert protected Config getConfig() { 8096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return mConfig; 8196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 8296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 8396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public void upgradeSettingsIfNeeded() { 8496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert upgradeShowWebSuggestionsIfNeeded(); 8596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 8696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 8796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public Intent getSearchableItemsIntent() { 8896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert Intent intent = new Intent(ACTION_SEARCHABLE_ITEMS); 8996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert intent.setPackage(getContext().getPackageName()); 9096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return intent; 9196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 9296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 9396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 9496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Gets the preference key of the preference for whether the given corpus 9596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * is enabled. The preference is stored in the {@link #PREFERENCES_NAME} 9696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * preferences file. 9796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 9896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public static String getCorpusEnabledPreference(Corpus corpus) { 9996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return CORPUS_ENABLED_PREF_PREFIX + corpus.getName(); 10096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 10196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 10296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public boolean isCorpusEnabled(Corpus corpus) { 10396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert boolean defaultEnabled = corpus.isCorpusDefaultEnabled(); 10496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert String sourceEnabledPref = getCorpusEnabledPreference(corpus); 10596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return getSearchPreferences().getBoolean(sourceEnabledPref, defaultEnabled); 10696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 10796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 10896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert protected SharedPreferences getSearchPreferences() { 10996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return getContext().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE); 11096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 11196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 11296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public boolean getShowWebSuggestions() { 11396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return getSearchPreferences().getBoolean(SHOW_WEB_SUGGESTIONS_PREF, true); 11496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 11596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 11696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 11796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Copies value from the old deprecated SHOW_WEB_SUGGESTIONS system setting. 11896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 11996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private void upgradeShowWebSuggestionsIfNeeded() { 12096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert SharedPreferences prefs = getSearchPreferences(); 12196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert if (!prefs.contains(SHOW_WEB_SUGGESTIONS_PREF)) { 12296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert // Default to true if the old setting is not set 12396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert boolean oldValue = Settings.System.getInt(getContext().getContentResolver(), 12496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert Settings.System.SHOW_WEB_SUGGESTIONS, 1) == 1; 12596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert prefs.edit().putBoolean(SHOW_WEB_SUGGESTIONS_PREF, oldValue).commit(); 12696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert Log.i(TAG, "Copied value from Settings.System.SHOW_WEB_SUGGESTIONS: " + oldValue); 12796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 12896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 12996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 13096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert /** 13196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert * Informs our listeners about the updated settings data. 13296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert */ 13396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public void broadcastSettingsChanged() { 13496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert // We use a message broadcast since the listeners could be in multiple processes. 13596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS_CHANGED); 13696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert Log.i(TAG, "Broadcasting: " + intent); 13796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert getContext().sendBroadcast(intent); 13896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 13996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 14096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public void addMenuItems(Menu menu) { 14196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert MenuInflater inflater = new MenuInflater(getContext()); 14296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert inflater.inflate(R.menu.settings, menu); 14396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert MenuItem item = menu.findItem(R.id.menu_settings); 14496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert item.setIntent(getSearchSettingsIntent()); 14596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 14696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 14796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public void updateMenuItems(Menu menu) { 14896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 14996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 15096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public Intent getSearchSettingsIntent() { 15196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert Intent settings = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS); 15296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert settings.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 15396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert settings.setPackage(getContext().getPackageName()); 15496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return settings; 15596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 15696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 15796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public int getNextVoiceSearchHintIndex(int size) { 15896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert int i = getAndIncrementIntPreference(getSearchPreferences(), 15996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert NEXT_VOICE_SEARCH_HINT_INDEX_PREF); 16096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return i % size; 16196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 16296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 16396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert // TODO: Could this be made atomic to avoid races? 16496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert private static int getAndIncrementIntPreference(SharedPreferences prefs, String name) { 16596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert int i = prefs.getInt(name, 0); 16696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert prefs.edit().putInt(name, i + 1).commit(); 16796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return i; 16896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 16996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 17096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public void resetVoiceSearchHintFirstSeenTime() { 17196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert getSearchPreferences().edit() 17296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert .putLong(FIRST_VOICE_HINT_DISPLAY_TIME, System.currentTimeMillis()).commit(); 17396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 17496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 17596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert public boolean haveVoiceSearchHintsExpired(int currentVoiceSearchVersion) { 17696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert SharedPreferences prefs = getSearchPreferences(); 17796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 17896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert if (currentVoiceSearchVersion != 0) { 17996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert long currentTime = System.currentTimeMillis(); 18096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert int lastVoiceSearchVersion = prefs.getInt(LAST_SEEN_VOICE_SEARCH_VERSION, 0); 18196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert long firstHintTime = prefs.getLong(FIRST_VOICE_HINT_DISPLAY_TIME, 0); 18296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert if (firstHintTime == 0 || currentVoiceSearchVersion != lastVoiceSearchVersion) { 18396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert prefs.edit() 18496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert .putInt(LAST_SEEN_VOICE_SEARCH_VERSION, currentVoiceSearchVersion) 18596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert .putLong(FIRST_VOICE_HINT_DISPLAY_TIME, currentTime) 18696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert .commit(); 18796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert firstHintTime = currentTime; 18896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 18996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert if (currentTime - firstHintTime > getConfig().getVoiceSearchHintActivePeriod()) { 19096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert if (DBG) Log.d(TAG, "Voice seach hint period expired; not showing hints."); 19196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return true; 19296fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } else { 19396fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return false; 19496fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 19596fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } else { 19696fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert if (DBG) Log.d(TAG, "Could not determine voice search version; not showing hints."); 19796fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert return true; 19896fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 19996fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert } 20096fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert 20196fec862c3d494aebcb4e1d93589a241385a2ba7Bjorn Bringert} 202