Config.java revision 848fa7a19abedc372452073abaf52780c7b6d78d
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 38 protected static final long SECOND_MILLIS = 1000L; 39 protected static final long MINUTE_MILLIS = 60L * SECOND_MILLIS; 40 protected static final long DAY_MILLIS = 86400000L; 41 42 private static final int NUM_SUGGESTIONS_ABOVE_KEYBOARD = 4; 43 private static final int NUM_PROMOTED_SOURCES = 3; 44 private static final int MAX_PROMOTED_SUGGESTIONS = 8; 45 private static final int MAX_RESULTS_PER_SOURCE = 50; 46 private static final int MAX_SHORTCUTS_PER_WEB_SOURCE = MAX_PROMOTED_SUGGESTIONS; 47 private static final int MAX_SHORTCUTS_PER_NON_WEB_SOURCE = 2; 48 private static final long SOURCE_TIMEOUT_MILLIS = 10000; 49 50 private static final int QUERY_THREAD_PRIORITY = 51 Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE; 52 53 private static final long MAX_STAT_AGE_MILLIS = 30 * DAY_MILLIS; 54 private static final int MIN_CLICKS_FOR_SOURCE_RANKING = 3; 55 private static final int MAX_SHORTCUTS_RETURNED = MAX_PROMOTED_SUGGESTIONS; 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 DISMISS_KEYBOARD_ON_SCROLL = true; 77 78 private final Context mContext; 79 private HashSet<String> mDefaultCorpora; 80 private HashSet<String> mHiddenCorpora; 81 82 /** 83 * Creates a new config that uses hard-coded default values. 84 */ 85 public Config(Context context) { 86 mContext = context; 87 } 88 89 protected Context getContext() { 90 return mContext; 91 } 92 93 /** 94 * Releases any resources used by the configuration object. 95 * 96 * Default implementation does nothing. 97 */ 98 public void close() { 99 } 100 101 private HashSet<String> loadResourceStringSet(int res) { 102 HashSet<String> defaultCorpora = new HashSet<String>(); 103 try { 104 String[] corpora = mContext.getResources().getStringArray(res); 105 for (String corpus : corpora) { 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(String corpusName) { 119 if (mDefaultCorpora == null) { 120 mDefaultCorpora = loadResourceStringSet(R.array.default_corpora); 121 } 122 return mDefaultCorpora.contains(corpusName); 123 } 124 125 /** 126 * Checks if the given corpus should be hidden from the corpus selection dialog. 127 */ 128 public synchronized boolean isCorpusHidden(String corpusName) { 129 if (mHiddenCorpora == null) { 130 mHiddenCorpora = loadResourceStringSet(R.array.hidden_corpora); 131 } 132 return mHiddenCorpora.contains(corpusName); 133 } 134 135 /** 136 * The number of promoted sources. 137 */ 138 public int getNumPromotedSources() { 139 return NUM_PROMOTED_SOURCES; 140 } 141 142 /** 143 * The number of suggestions visible above the onscreen keyboard. 144 */ 145 public int getNumSuggestionsAboveKeyboard() { 146 try { 147 // Get the list of default corpora from a resource, which allows vendor overlays. 148 return mContext.getResources().getInteger(R.integer.num_suggestions_above_keyboard); 149 } catch (Resources.NotFoundException ex) { 150 Log.e(TAG, "Could not load num_suggestions_above_keyboard", ex); 151 return NUM_SUGGESTIONS_ABOVE_KEYBOARD; 152 } 153 } 154 155 /** 156 * The maximum number of suggestions to promote. 157 */ 158 public int getMaxPromotedSuggestions() { 159 try { 160 return mContext.getResources().getInteger(R.integer.max_promoted_suggestions); 161 } catch (Resources.NotFoundException ex) { 162 Log.e(TAG, "Could not load max_promoted_suggestions", ex); 163 return MAX_PROMOTED_SUGGESTIONS; 164 } 165 } 166 167 /** 168 * The number of results to ask each source for. 169 */ 170 public int getMaxResultsPerSource() { 171 return MAX_RESULTS_PER_SOURCE; 172 } 173 174 /** 175 * The maximum number of shortcuts to show for the web source in All mode. 176 */ 177 public int getMaxShortcutsPerWebSource() { 178 return MAX_SHORTCUTS_PER_WEB_SOURCE; 179 } 180 181 /** 182 * The maximum number of shortcuts to show for each non-web source in All mode. 183 */ 184 public int getMaxShortcutsPerNonWebSource() { 185 return MAX_SHORTCUTS_PER_NON_WEB_SOURCE; 186 } 187 188 /** 189 * The timeout for querying each source, in milliseconds. 190 */ 191 public long getSourceTimeoutMillis() { 192 return SOURCE_TIMEOUT_MILLIS; 193 } 194 195 /** 196 * The priority of query threads. 197 * 198 * @return A thread priority, as defined in {@link Process}. 199 */ 200 public int getQueryThreadPriority() { 201 return QUERY_THREAD_PRIORITY; 202 } 203 204 /** 205 * The maximum age of log data used for shortcuts. 206 */ 207 public long getMaxStatAgeMillis(){ 208 return MAX_STAT_AGE_MILLIS; 209 } 210 211 /** 212 * The minimum number of clicks needed to rank a source. 213 */ 214 public int getMinClicksForSourceRanking(){ 215 return MIN_CLICKS_FOR_SOURCE_RANKING; 216 } 217 218 /** 219 * The maximum number of shortcuts shown. 220 */ 221 public int getMaxShortcutsReturned(){ 222 return MAX_SHORTCUTS_RETURNED; 223 } 224 225 public int getNumWebCorpusThreads() { 226 return NUM_WEB_CORPUS_THREADS; 227 } 228 229 /** 230 * How often query latency should be logged. 231 * 232 * @return An integer in the range 0-1000. 0 means that no latency events 233 * should be logged. 1000 means that all latency events should be logged. 234 */ 235 public int getLatencyLogFrequency() { 236 return LATENCY_LOG_FREQUENCY; 237 } 238 239 /** 240 * The delay in milliseconds before suggestions are updated while typing. 241 * If a new character is typed before this timeout expires, the timeout is reset. 242 */ 243 public long getTypingUpdateSuggestionsDelayMillis() { 244 return TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS; 245 } 246 247 /** 248 * The delay in milliseconds before corpus results are published. 249 * If a new result arrives before this timeout expires, the timeout is reset. 250 */ 251 public long getPublishResultDelayMillis() { 252 return PUBLISH_RESULT_DELAY_MILLIS; 253 } 254 255 public boolean allowVoiceSearchHints() { 256 return true; 257 } 258 259 /** 260 * The period of time for which after installing voice search we should consider showing voice 261 * search hints. 262 * 263 * @return The period in milliseconds. 264 */ 265 public long getVoiceSearchHintActivePeriod() { 266 return VOICE_SEARCH_HINT_ACTIVE_PERIOD; 267 } 268 269 /** 270 * The time interval at which we should consider whether or not to show some voice search hints. 271 * 272 * @return The period in milliseconds. 273 */ 274 public long getVoiceSearchHintUpdatePeriod() { 275 return VOICE_SEARCH_HINT_UPDATE_INTERVAL; 276 } 277 278 /** 279 * The time interval at which, on average, voice search hints are displayed. 280 * 281 * @return The period in milliseconds. 282 */ 283 public long getVoiceSearchHintShowPeriod() { 284 return VOICE_SEARCH_HINT_SHOW_PERIOD_MILLIS; 285 } 286 287 /** 288 * The amount of time for which voice search hints are displayed in one go. 289 * 290 * @return The period in milliseconds. 291 */ 292 public long getVoiceSearchHintVisibleTime() { 293 return VOICE_SEARCH_HINT_VISIBLE_PERIOD; 294 } 295 296 /** 297 * The period that we change voice search hints at while they're being displayed. 298 * 299 * @return The period in milliseconds. 300 */ 301 public long getVoiceSearchHintChangePeriod() { 302 return VOICE_SEARCH_HINT_CHANGE_PERIOD; 303 } 304 305 public boolean isKeyboardDismissedOnScroll() { 306 try { 307 // Get the keyboard dismiss policy 308 return mContext.getResources().getBoolean(R.bool.dismiss_keyboard_on_scroll); 309 } catch (Resources.NotFoundException ex) { 310 Log.e(TAG, "Could not load dismiss_keyboard_on_scroll", ex); 311 return DISMISS_KEYBOARD_ON_SCROLL; 312 } 313 } 314} 315