Home | History | Annotate | Download | only in quicksearchbox
      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 
     17 package com.android.quicksearchbox;
     18 
     19 import android.app.AlarmManager;
     20 import android.content.Context;
     21 import android.net.Uri;
     22 import android.os.Process;
     23 import android.util.Log;
     24 
     25 import 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  */
     34 public 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_PROMOTED_SOURCES = 3;
     44     private static final int MAX_RESULTS_PER_SOURCE = 50;
     45     private static final long SOURCE_TIMEOUT_MILLIS = 10000;
     46 
     47     private static final int QUERY_THREAD_PRIORITY =
     48             Process.THREAD_PRIORITY_BACKGROUND + Process.THREAD_PRIORITY_MORE_FAVORABLE;
     49 
     50     private static final long MAX_STAT_AGE_MILLIS = 30 * DAY_MILLIS;
     51     private static final int MIN_CLICKS_FOR_SOURCE_RANKING = 3;
     52 
     53     private static final int NUM_WEB_CORPUS_THREADS = 2;
     54 
     55     private static final int LATENCY_LOG_FREQUENCY = 1000;
     56 
     57     private static final long TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS = 100;
     58     private static final long PUBLISH_RESULT_DELAY_MILLIS = 200;
     59 
     60     private static final long VOICE_SEARCH_HINT_ACTIVE_PERIOD = 7L * DAY_MILLIS;
     61 
     62     private static final long VOICE_SEARCH_HINT_UPDATE_INTERVAL
     63             = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
     64 
     65     private static final long VOICE_SEARCH_HINT_SHOW_PERIOD_MILLIS
     66             = AlarmManager.INTERVAL_HOUR * 2;
     67 
     68     private static final long VOICE_SEARCH_HINT_CHANGE_PERIOD = 2L * MINUTE_MILLIS;
     69 
     70     private static final long VOICE_SEARCH_HINT_VISIBLE_PERIOD = 6L * MINUTE_MILLIS;
     71 
     72     private static final int HTTP_CONNECT_TIMEOUT_MILLIS = 4000;
     73     private static final int HTTP_READ_TIMEOUT_MILLIS = 4000;
     74 
     75     private static final String USER_AGENT = "Android/1.0";
     76 
     77     private final Context mContext;
     78     private HashSet<String> mDefaultCorpora;
     79     private HashSet<String> mHiddenCorpora;
     80     private HashSet<String> mDefaultCorporaSuggestUris;
     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         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     }
    110 
    111     /**
    112      * Checks if we trust the given source not to be spammy.
    113      */
    114     public synchronized boolean isCorpusEnabledByDefault(Corpus corpus) {
    115         if (DBG) Log.d(TAG, "isCorpusEnabledByDefault(" + corpus.getName() + ")");
    116         if (mDefaultCorpora == null) {
    117             mDefaultCorpora = loadResourceStringSet(R.array.default_corpora);
    118         }
    119         if (mDefaultCorpora.contains(corpus.getName())) {
    120             if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default");
    121             return true;
    122         }
    123 
    124         if (mDefaultCorporaSuggestUris == null) {
    125             mDefaultCorporaSuggestUris = loadResourceStringSet(
    126                     R.array.default_corpora_suggest_uris);
    127         }
    128 
    129         for (Source s : corpus.getSources()) {
    130             String uri = s.getSuggestUri();
    131             if (DBG) Log.d(TAG, "Suggest URI for " + corpus.getName() + ": " + uri);
    132             if (mDefaultCorporaSuggestUris.contains(uri)) {
    133                 if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " IS default");
    134                 return true;
    135             }
    136         }
    137         if (DBG) Log.d(TAG, "Corpus " + corpus.getName() + " is NOT default");
    138         return false;
    139     }
    140 
    141     /**
    142      * Checks if the given corpus should be hidden from the corpus selection dialog.
    143      */
    144     public synchronized boolean isCorpusHidden(String corpusName) {
    145         if (mHiddenCorpora == null) {
    146             mHiddenCorpora = loadResourceStringSet(R.array.hidden_corpora);
    147         }
    148         return mHiddenCorpora.contains(corpusName);
    149     }
    150 
    151     /**
    152      * The number of promoted sources.
    153      */
    154     public int getNumPromotedSources() {
    155         return NUM_PROMOTED_SOURCES;
    156     }
    157 
    158     /**
    159      * The number of suggestions visible above the onscreen keyboard.
    160      */
    161     public int getNumSuggestionsAboveKeyboard() {
    162         // Get the list of default corpora from a resource, which allows vendor overlays.
    163         return mContext.getResources().getInteger(R.integer.num_suggestions_above_keyboard);
    164     }
    165 
    166     /**
    167      * The maximum number of suggestions to promote.
    168      */
    169     public int getMaxPromotedSuggestions() {
    170         return mContext.getResources().getInteger(R.integer.max_promoted_suggestions);
    171     }
    172 
    173     public int getMaxPromotedResults() {
    174         return mContext.getResources().getInteger(R.integer.max_promoted_results);
    175     }
    176 
    177     /**
    178      * The number of results to ask each source for.
    179      */
    180     public int getMaxResultsPerSource() {
    181         return MAX_RESULTS_PER_SOURCE;
    182     }
    183 
    184     /**
    185      * The maximum number of shortcuts to show for the web source in All mode.
    186      */
    187     public int getMaxShortcutsPerWebSource() {
    188         return mContext.getResources().getInteger(R.integer.max_shortcuts_per_web_source);
    189     }
    190 
    191     /**
    192      * The maximum number of shortcuts to show for each non-web source in All mode.
    193      */
    194     public int getMaxShortcutsPerNonWebSource() {
    195         return mContext.getResources().getInteger(R.integer.max_shortcuts_per_non_web_source);
    196     }
    197 
    198     /**
    199      * Gets the maximum number of shortcuts that will be shown from the given source.
    200      */
    201     public int getMaxShortcuts(String sourceName) {
    202         return getMaxShortcutsPerNonWebSource();
    203     }
    204 
    205     /**
    206      * The timeout for querying each source, in milliseconds.
    207      */
    208     public long getSourceTimeoutMillis() {
    209         return SOURCE_TIMEOUT_MILLIS;
    210     }
    211 
    212     /**
    213      * The priority of query threads.
    214      *
    215      * @return A thread priority, as defined in {@link Process}.
    216      */
    217     public int getQueryThreadPriority() {
    218         return QUERY_THREAD_PRIORITY;
    219     }
    220 
    221     /**
    222      * The maximum age of log data used for shortcuts.
    223      */
    224     public long getMaxStatAgeMillis(){
    225         return MAX_STAT_AGE_MILLIS;
    226     }
    227 
    228     /**
    229      * The minimum number of clicks needed to rank a source.
    230      */
    231     public int getMinClicksForSourceRanking(){
    232         return MIN_CLICKS_FOR_SOURCE_RANKING;
    233     }
    234 
    235     public int getNumWebCorpusThreads() {
    236         return NUM_WEB_CORPUS_THREADS;
    237     }
    238 
    239     /**
    240      * How often query latency should be logged.
    241      *
    242      * @return An integer in the range 0-1000. 0 means that no latency events
    243      *         should be logged. 1000 means that all latency events should be logged.
    244      */
    245     public int getLatencyLogFrequency() {
    246         return LATENCY_LOG_FREQUENCY;
    247     }
    248 
    249     /**
    250      * The delay in milliseconds before suggestions are updated while typing.
    251      * If a new character is typed before this timeout expires, the timeout is reset.
    252      */
    253     public long getTypingUpdateSuggestionsDelayMillis() {
    254         return TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS;
    255     }
    256 
    257     /**
    258      * The delay in milliseconds before corpus results are published.
    259      * If a new result arrives before this timeout expires, the timeout is reset.
    260      */
    261     public long getPublishResultDelayMillis() {
    262         return PUBLISH_RESULT_DELAY_MILLIS;
    263     }
    264 
    265     public boolean allowVoiceSearchHints() {
    266         return true;
    267     }
    268 
    269     /**
    270      * The period of time for which after installing voice search we should consider showing voice
    271      * search hints.
    272      *
    273      * @return The period in milliseconds.
    274      */
    275     public long getVoiceSearchHintActivePeriod() {
    276         return VOICE_SEARCH_HINT_ACTIVE_PERIOD;
    277     }
    278 
    279     /**
    280      * The time interval at which we should consider whether or not to show some voice search hints.
    281      *
    282      * @return The period in milliseconds.
    283      */
    284     public long getVoiceSearchHintUpdatePeriod() {
    285         return VOICE_SEARCH_HINT_UPDATE_INTERVAL;
    286     }
    287 
    288     /**
    289      * The time interval at which, on average, voice search hints are displayed.
    290      *
    291      * @return The period in milliseconds.
    292      */
    293     public long getVoiceSearchHintShowPeriod() {
    294         return VOICE_SEARCH_HINT_SHOW_PERIOD_MILLIS;
    295     }
    296 
    297     /**
    298      * The amount of time for which voice search hints are displayed in one go.
    299      *
    300      * @return The period in milliseconds.
    301      */
    302     public long getVoiceSearchHintVisibleTime() {
    303         return VOICE_SEARCH_HINT_VISIBLE_PERIOD;
    304     }
    305 
    306     /**
    307      * The period that we change voice search hints at while they're being displayed.
    308      *
    309      * @return The period in milliseconds.
    310      */
    311     public long getVoiceSearchHintChangePeriod() {
    312         return VOICE_SEARCH_HINT_CHANGE_PERIOD;
    313     }
    314 
    315     public boolean showSuggestionsForZeroQuery() {
    316         // Get the list of default corpora from a resource, which allows vendor overlays.
    317         return mContext.getResources().getBoolean(R.bool.show_zero_query_suggestions);
    318     }
    319 
    320     public boolean showShortcutsForZeroQuery() {
    321         // Get the list of default corpora from a resource, which allows vendor overlays.
    322         return mContext.getResources().getBoolean(R.bool.show_zero_query_shortcuts);
    323     }
    324 
    325     public boolean showScrollingSuggestions() {
    326         return mContext.getResources().getBoolean(R.bool.show_scrolling_suggestions);
    327     }
    328 
    329     public boolean showScrollingResults() {
    330         return mContext.getResources().getBoolean(R.bool.show_scrolling_results);
    331     }
    332 
    333     public Uri getHelpUrl(String activity) {
    334         return null;
    335     }
    336 
    337     public int getHttpConnectTimeout() {
    338         return HTTP_CONNECT_TIMEOUT_MILLIS;
    339     }
    340 
    341     public int getHttpReadTimeout() {
    342         return HTTP_READ_TIMEOUT_MILLIS;
    343     }
    344 
    345     public String getUserAgent() {
    346         return USER_AGENT;
    347     }
    348 }
    349