Config.java revision 53aab8c4459f45664d04ec882d67094c52b78695
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.quicksearchbox; 18 19import android.app.AlarmManager; 20import android.content.Context; 21import android.content.res.Resources; 22import android.os.Process; 23import android.util.Log; 24 25import java.util.HashSet; 26 27/** 28 * Provides values for configurable parameters in all of QSB. 29 * 30 * All the methods in this class return fixed default values. Subclasses may 31 * make these values server-side settable. 32 * 33 */ 34public class Config { 35 36 private static final String TAG = "QSB.Config"; 37 private static final boolean DBG = false; 38 39 protected static final long SECOND_MILLIS = 1000L; 40 protected static final long MINUTE_MILLIS = 60L * SECOND_MILLIS; 41 protected static final long DAY_MILLIS = 86400000L; 42 43 private static final int NUM_SUGGESTIONS_ABOVE_KEYBOARD = 4; 44 private static final int NUM_PROMOTED_SOURCES = 3; 45 private static final int MAX_PROMOTED_SUGGESTIONS = 8; 46 private static final int MAX_RESULTS_PER_SOURCE = 50; 47 private static final int MAX_SHORTCUTS_PER_WEB_SOURCE = MAX_PROMOTED_SUGGESTIONS; 48 private static final int MAX_SHORTCUTS_PER_NON_WEB_SOURCE = 2; 49 private static final long SOURCE_TIMEOUT_MILLIS = 10000; 50 51 private static final int QUERY_THREAD_PRIORITY = 52 Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE; 53 54 private static final long MAX_STAT_AGE_MILLIS = 30 * DAY_MILLIS; 55 private static final int MIN_CLICKS_FOR_SOURCE_RANKING = 3; 56 57 private static final int NUM_WEB_CORPUS_THREADS = 2; 58 59 private static final int LATENCY_LOG_FREQUENCY = 1000; 60 61 private static final long TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS = 100; 62 private static final long PUBLISH_RESULT_DELAY_MILLIS = 200; 63 64 private static final long VOICE_SEARCH_HINT_ACTIVE_PERIOD = 7L * DAY_MILLIS; 65 66 private static final long VOICE_SEARCH_HINT_UPDATE_INTERVAL 67 = AlarmManager.INTERVAL_FIFTEEN_MINUTES; 68 69 private static final long VOICE_SEARCH_HINT_SHOW_PERIOD_MILLIS 70 = AlarmManager.INTERVAL_HOUR * 2; 71 72 private static final long VOICE_SEARCH_HINT_CHANGE_PERIOD = 2L * MINUTE_MILLIS; 73 74 private static final long VOICE_SEARCH_HINT_VISIBLE_PERIOD = 6L * MINUTE_MILLIS; 75 76 private final Context mContext; 77 private HashSet<String> mDefaultCorpora; 78 private HashSet<String> mHiddenCorpora; 79 private HashSet<String> mDefaultCorporaSuggestUris; 80 81 /** 82 * Creates a new config that uses hard-coded default values. 83 */ 84 public Config(Context context) { 85 mContext = context; 86 } 87 88 protected Context getContext() { 89 return mContext; 90 } 91 92 /** 93 * Releases any resources used by the configuration object. 94 * 95 * Default implementation does nothing. 96 */ 97 public void close() { 98 } 99 100 private HashSet<String> loadResourceStringSet(int res) { 101 HashSet<String> defaultCorpora = new HashSet<String>(); 102 try { 103 String[] corpora = mContext.getResources().getStringArray(res); 104 for (String corpus : corpora) { 105 if (DBG) Log.d(TAG, "Default corpus: " + corpus); 106 defaultCorpora.add(corpus); 107 } 108 return defaultCorpora; 109 } catch (Resources.NotFoundException ex) { 110 Log.e(TAG, "Could not load resource string set", ex); 111 return defaultCorpora; 112 } 113 } 114 115 /** 116 * Checks if we trust the given source not to be spammy. 117 */ 118 public synchronized boolean isCorpusEnabledByDefault(Corpus corpus) { 119 if (DBG) Log.d(TAG, "isCorpusEnabledByDefault(" + corpus.getName() + ")"); 120 if (mDefaultCorpora == null) { 121 mDefaultCorpora = loadResourceStringSet(R.array.default_corpora); 122 } 123 if (mDefaultCorpora.contains(corpus.getName())) { 124 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default"); 125 return true; 126 } 127 128 if (mDefaultCorporaSuggestUris == null) { 129 mDefaultCorporaSuggestUris = loadResourceStringSet( 130 R.array.default_corpora_suggest_uris); 131 } 132 133 for (Source s : corpus.getSources()) { 134 String uri = s.getSuggestUri(); 135 if (DBG) Log.d(TAG, "Suggest URI for " + corpus.getName() + ": " + uri); 136 if (mDefaultCorporaSuggestUris.contains(uri)) { 137 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default"); 138 return true; 139 } 140 } 141 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " is NOT default"); 142 return false; 143 } 144 145 /** 146 * Checks if the given corpus should be hidden from the corpus selection dialog. 147 */ 148 public synchronized boolean isCorpusHidden(String corpusName) { 149 if (mHiddenCorpora == null) { 150 mHiddenCorpora = loadResourceStringSet(R.array.hidden_corpora); 151 } 152 return mHiddenCorpora.contains(corpusName); 153 } 154 155 /** 156 * The number of promoted sources. 157 */ 158 public int getNumPromotedSources() { 159 return NUM_PROMOTED_SOURCES; 160 } 161 162 /** 163 * The number of suggestions visible above the onscreen keyboard. 164 */ 165 public int getNumSuggestionsAboveKeyboard() { 166 try { 167 // Get the list of default corpora from a resource, which allows vendor overlays. 168 return mContext.getResources().getInteger(R.integer.num_suggestions_above_keyboard); 169 } catch (Resources.NotFoundException ex) { 170 Log.e(TAG, "Could not load num_suggestions_above_keyboard", ex); 171 return NUM_SUGGESTIONS_ABOVE_KEYBOARD; 172 } 173 } 174 175 /** 176 * The maximum number of suggestions to promote. 177 */ 178 public int getMaxPromotedSuggestions() { 179 try { 180 return mContext.getResources().getInteger(R.integer.max_promoted_suggestions); 181 } catch (Resources.NotFoundException ex) { 182 Log.e(TAG, "Could not load max_promoted_suggestions", ex); 183 return MAX_PROMOTED_SUGGESTIONS; 184 } 185 } 186 187 /** 188 * The number of results to ask each source for. 189 */ 190 public int getMaxResultsPerSource() { 191 return MAX_RESULTS_PER_SOURCE; 192 } 193 194 /** 195 * The maximum number of shortcuts to show for the web source in All mode. 196 */ 197 public int getMaxShortcutsPerWebSource() { 198 return MAX_SHORTCUTS_PER_WEB_SOURCE; 199 } 200 201 /** 202 * The maximum number of shortcuts to show for each non-web source in All mode. 203 */ 204 public int getMaxShortcutsPerNonWebSource() { 205 return MAX_SHORTCUTS_PER_NON_WEB_SOURCE; 206 } 207 208 /** 209 * Gets the maximum number of shortcuts that will be shown from the given source. 210 */ 211 public int getMaxShortcuts(String sourceName) { 212 return getMaxShortcutsPerNonWebSource(); 213 } 214 215 /** 216 * The timeout for querying each source, in milliseconds. 217 */ 218 public long getSourceTimeoutMillis() { 219 return SOURCE_TIMEOUT_MILLIS; 220 } 221 222 /** 223 * The priority of query threads. 224 * 225 * @return A thread priority, as defined in {@link Process}. 226 */ 227 public int getQueryThreadPriority() { 228 return QUERY_THREAD_PRIORITY; 229 } 230 231 /** 232 * The maximum age of log data used for shortcuts. 233 */ 234 public long getMaxStatAgeMillis(){ 235 return MAX_STAT_AGE_MILLIS; 236 } 237 238 /** 239 * The minimum number of clicks needed to rank a source. 240 */ 241 public int getMinClicksForSourceRanking(){ 242 return MIN_CLICKS_FOR_SOURCE_RANKING; 243 } 244 245 public int getNumWebCorpusThreads() { 246 return NUM_WEB_CORPUS_THREADS; 247 } 248 249 /** 250 * How often query latency should be logged. 251 * 252 * @return An integer in the range 0-1000. 0 means that no latency events 253 * should be logged. 1000 means that all latency events should be logged. 254 */ 255 public int getLatencyLogFrequency() { 256 return LATENCY_LOG_FREQUENCY; 257 } 258 259 /** 260 * The delay in milliseconds before suggestions are updated while typing. 261 * If a new character is typed before this timeout expires, the timeout is reset. 262 */ 263 public long getTypingUpdateSuggestionsDelayMillis() { 264 return TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS; 265 } 266 267 /** 268 * The delay in milliseconds before corpus results are published. 269 * If a new result arrives before this timeout expires, the timeout is reset. 270 */ 271 public long getPublishResultDelayMillis() { 272 return PUBLISH_RESULT_DELAY_MILLIS; 273 } 274 275 public boolean allowVoiceSearchHints() { 276 return true; 277 } 278 279 /** 280 * The period of time for which after installing voice search we should consider showing voice 281 * search hints. 282 * 283 * @return The period in milliseconds. 284 */ 285 public long getVoiceSearchHintActivePeriod() { 286 return VOICE_SEARCH_HINT_ACTIVE_PERIOD; 287 } 288 289 /** 290 * The time interval at which we should consider whether or not to show some voice search hints. 291 * 292 * @return The period in milliseconds. 293 */ 294 public long getVoiceSearchHintUpdatePeriod() { 295 return VOICE_SEARCH_HINT_UPDATE_INTERVAL; 296 } 297 298 /** 299 * The time interval at which, on average, voice search hints are displayed. 300 * 301 * @return The period in milliseconds. 302 */ 303 public long getVoiceSearchHintShowPeriod() { 304 return VOICE_SEARCH_HINT_SHOW_PERIOD_MILLIS; 305 } 306 307 /** 308 * The amount of time for which voice search hints are displayed in one go. 309 * 310 * @return The period in milliseconds. 311 */ 312 public long getVoiceSearchHintVisibleTime() { 313 return VOICE_SEARCH_HINT_VISIBLE_PERIOD; 314 } 315 316 /** 317 * The period that we change voice search hints at while they're being displayed. 318 * 319 * @return The period in milliseconds. 320 */ 321 public long getVoiceSearchHintChangePeriod() { 322 return VOICE_SEARCH_HINT_CHANGE_PERIOD; 323 } 324 325} 326