Config.java revision fdb80c2962c88ac62dcd7ee7f2fab1857b61506b
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 static final boolean SHOW_SUGGESTIONS_FOR_ZERO_QUERY = false; 77 78 private static final boolean SHOW_SHORTCUTS_FOR_ZERO_QUERY = true; 79 80 private final Context mContext; 81 private HashSet<String> mDefaultCorpora; 82 private HashSet<String> mHiddenCorpora; 83 private HashSet<String> mDefaultCorporaSuggestUris; 84 85 /** 86 * Creates a new config that uses hard-coded default values. 87 */ 88 public Config(Context context) { 89 mContext = context; 90 } 91 92 protected Context getContext() { 93 return mContext; 94 } 95 96 /** 97 * Releases any resources used by the configuration object. 98 * 99 * Default implementation does nothing. 100 */ 101 public void close() { 102 } 103 104 private HashSet<String> loadResourceStringSet(int res) { 105 HashSet<String> defaultCorpora = new HashSet<String>(); 106 try { 107 String[] corpora = mContext.getResources().getStringArray(res); 108 for (String corpus : corpora) { 109 if (DBG) Log.d(TAG, "Default corpus: " + corpus); 110 defaultCorpora.add(corpus); 111 } 112 return defaultCorpora; 113 } catch (Resources.NotFoundException ex) { 114 Log.e(TAG, "Could not load resource string set", ex); 115 return defaultCorpora; 116 } 117 } 118 119 /** 120 * Checks if we trust the given source not to be spammy. 121 */ 122 public synchronized boolean isCorpusEnabledByDefault(Corpus corpus) { 123 if (DBG) Log.d(TAG, "isCorpusEnabledByDefault(" + corpus.getName() + ")"); 124 if (mDefaultCorpora == null) { 125 mDefaultCorpora = loadResourceStringSet(R.array.default_corpora); 126 } 127 if (mDefaultCorpora.contains(corpus.getName())) { 128 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default"); 129 return true; 130 } 131 132 if (mDefaultCorporaSuggestUris == null) { 133 mDefaultCorporaSuggestUris = loadResourceStringSet( 134 R.array.default_corpora_suggest_uris); 135 } 136 137 for (Source s : corpus.getSources()) { 138 String uri = s.getSuggestUri(); 139 if (DBG) Log.d(TAG, "Suggest URI for " + corpus.getName() + ": " + uri); 140 if (mDefaultCorporaSuggestUris.contains(uri)) { 141 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default"); 142 return true; 143 } 144 } 145 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " is NOT default"); 146 return false; 147 } 148 149 /** 150 * Checks if the given corpus should be hidden from the corpus selection dialog. 151 */ 152 public synchronized boolean isCorpusHidden(String corpusName) { 153 if (mHiddenCorpora == null) { 154 mHiddenCorpora = loadResourceStringSet(R.array.hidden_corpora); 155 } 156 return mHiddenCorpora.contains(corpusName); 157 } 158 159 /** 160 * The number of promoted sources. 161 */ 162 public int getNumPromotedSources() { 163 return NUM_PROMOTED_SOURCES; 164 } 165 166 /** 167 * The number of suggestions visible above the onscreen keyboard. 168 */ 169 public int getNumSuggestionsAboveKeyboard() { 170 try { 171 // Get the list of default corpora from a resource, which allows vendor overlays. 172 return mContext.getResources().getInteger(R.integer.num_suggestions_above_keyboard); 173 } catch (Resources.NotFoundException ex) { 174 Log.e(TAG, "Could not load num_suggestions_above_keyboard", ex); 175 return NUM_SUGGESTIONS_ABOVE_KEYBOARD; 176 } 177 } 178 179 /** 180 * The maximum number of suggestions to promote. 181 */ 182 public int getMaxPromotedSuggestions() { 183 try { 184 return mContext.getResources().getInteger(R.integer.max_promoted_suggestions); 185 } catch (Resources.NotFoundException ex) { 186 Log.e(TAG, "Could not load max_promoted_suggestions", ex); 187 return MAX_PROMOTED_SUGGESTIONS; 188 } 189 } 190 191 /** 192 * The number of results to ask each source for. 193 */ 194 public int getMaxResultsPerSource() { 195 return MAX_RESULTS_PER_SOURCE; 196 } 197 198 /** 199 * The maximum number of shortcuts to show for the web source in All mode. 200 */ 201 public int getMaxShortcutsPerWebSource() { 202 return MAX_SHORTCUTS_PER_WEB_SOURCE; 203 } 204 205 /** 206 * The maximum number of shortcuts to show for each non-web source in All mode. 207 */ 208 public int getMaxShortcutsPerNonWebSource() { 209 return MAX_SHORTCUTS_PER_NON_WEB_SOURCE; 210 } 211 212 /** 213 * Gets the maximum number of shortcuts that will be shown from the given source. 214 */ 215 public int getMaxShortcuts(String sourceName) { 216 return getMaxShortcutsPerNonWebSource(); 217 } 218 219 /** 220 * The timeout for querying each source, in milliseconds. 221 */ 222 public long getSourceTimeoutMillis() { 223 return SOURCE_TIMEOUT_MILLIS; 224 } 225 226 /** 227 * The priority of query threads. 228 * 229 * @return A thread priority, as defined in {@link Process}. 230 */ 231 public int getQueryThreadPriority() { 232 return QUERY_THREAD_PRIORITY; 233 } 234 235 /** 236 * The maximum age of log data used for shortcuts. 237 */ 238 public long getMaxStatAgeMillis(){ 239 return MAX_STAT_AGE_MILLIS; 240 } 241 242 /** 243 * The minimum number of clicks needed to rank a source. 244 */ 245 public int getMinClicksForSourceRanking(){ 246 return MIN_CLICKS_FOR_SOURCE_RANKING; 247 } 248 249 public int getNumWebCorpusThreads() { 250 return NUM_WEB_CORPUS_THREADS; 251 } 252 253 /** 254 * How often query latency should be logged. 255 * 256 * @return An integer in the range 0-1000. 0 means that no latency events 257 * should be logged. 1000 means that all latency events should be logged. 258 */ 259 public int getLatencyLogFrequency() { 260 return LATENCY_LOG_FREQUENCY; 261 } 262 263 /** 264 * The delay in milliseconds before suggestions are updated while typing. 265 * If a new character is typed before this timeout expires, the timeout is reset. 266 */ 267 public long getTypingUpdateSuggestionsDelayMillis() { 268 return TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS; 269 } 270 271 /** 272 * The delay in milliseconds before corpus results are published. 273 * If a new result arrives before this timeout expires, the timeout is reset. 274 */ 275 public long getPublishResultDelayMillis() { 276 return PUBLISH_RESULT_DELAY_MILLIS; 277 } 278 279 public boolean allowVoiceSearchHints() { 280 return true; 281 } 282 283 /** 284 * The period of time for which after installing voice search we should consider showing voice 285 * search hints. 286 * 287 * @return The period in milliseconds. 288 */ 289 public long getVoiceSearchHintActivePeriod() { 290 return VOICE_SEARCH_HINT_ACTIVE_PERIOD; 291 } 292 293 /** 294 * The time interval at which we should consider whether or not to show some voice search hints. 295 * 296 * @return The period in milliseconds. 297 */ 298 public long getVoiceSearchHintUpdatePeriod() { 299 return VOICE_SEARCH_HINT_UPDATE_INTERVAL; 300 } 301 302 /** 303 * The time interval at which, on average, voice search hints are displayed. 304 * 305 * @return The period in milliseconds. 306 */ 307 public long getVoiceSearchHintShowPeriod() { 308 return VOICE_SEARCH_HINT_SHOW_PERIOD_MILLIS; 309 } 310 311 /** 312 * The amount of time for which voice search hints are displayed in one go. 313 * 314 * @return The period in milliseconds. 315 */ 316 public long getVoiceSearchHintVisibleTime() { 317 return VOICE_SEARCH_HINT_VISIBLE_PERIOD; 318 } 319 320 /** 321 * The period that we change voice search hints at while they're being displayed. 322 * 323 * @return The period in milliseconds. 324 */ 325 public long getVoiceSearchHintChangePeriod() { 326 return VOICE_SEARCH_HINT_CHANGE_PERIOD; 327 } 328 329 public boolean showSuggestionsForZeroQuery() { 330 try { 331 // Get the list of default corpora from a resource, which allows vendor overlays. 332 return mContext.getResources().getBoolean(R.bool.show_zero_query_suggestions); 333 } catch (Resources.NotFoundException ex) { 334 Log.e(TAG, "Could not load show_zero_query_suggestions", ex); 335 return SHOW_SUGGESTIONS_FOR_ZERO_QUERY; 336 } 337 } 338 339 public boolean showShortcutsForZeroQuery() { 340 try { 341 // Get the list of default corpora from a resource, which allows vendor overlays. 342 return mContext.getResources().getBoolean(R.bool.show_zero_query_shortcuts); 343 } catch (Resources.NotFoundException ex) { 344 Log.e(TAG, "Could not load show_zero_query_shortcuts", ex); 345 return SHOW_SHORTCUTS_FOR_ZERO_QUERY; 346 } 347 } 348 349 public boolean showScrollingSuggestions() { 350 try { 351 return mContext.getResources().getBoolean(R.bool.show_scrolling_suggestions); 352 } catch (Resources.NotFoundException ex) { 353 Log.e(TAG, "Could not load show_zero_query_shortcuts", ex); 354 return true; 355 } 356 } 357 358} 359