Config.java revision 08ff0a7cb6b99db79508fa3124730eb81411bc56
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.content.Context;
20import android.content.res.Resources;
21import android.os.Process;
22import android.util.Log;
23
24import java.util.HashSet;
25
26/**
27 * Provides values for configurable parameters in all of QSB.
28 *
29 * All the methods in this class return fixed default values. Subclasses may
30 * make these values server-side settable.
31 *
32 */
33public class Config {
34
35    private static final String TAG = "QSB.Config";
36
37    private static final long DAY_MILLIS = 86400000L;
38
39    private static final int NUM_SUGGESTIONS_ABOVE_KEYBOARD = 4;
40    private static final int NUM_PROMOTED_SOURCES = 3;
41    private static final int MAX_PROMOTED_SUGGESTIONS = 8;
42    private static final int MAX_RESULTS_PER_SOURCE = 50;
43    private static final int MAX_SHORTCUTS_PER_WEB_SOURCE = MAX_PROMOTED_SUGGESTIONS;
44    private static final int MAX_SHORTCUTS_PER_NON_WEB_SOURCE = 2;
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    private static final int MAX_SHORTCUTS_RETURNED = MAX_PROMOTED_SUGGESTIONS;
53
54    private static final int NUM_WEB_CORPUS_THREADS = 2;
55
56    private static final int LATENCY_LOG_FREQUENCY = 1000;
57
58    private static final long TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS = 100;
59    private static final long PUBLISH_RESULT_DELAY_MILLIS = 200;
60
61    private final Context mContext;
62    private HashSet<String> mDefaultCorpora;
63    private HashSet<String> mHiddenCorpora;
64
65    /**
66     * Creates a new config that uses hard-coded default values.
67     */
68    public Config(Context context) {
69        mContext = context;
70    }
71
72    protected Context getContext() {
73        return mContext;
74    }
75
76    /**
77     * Releases any resources used by the configuration object.
78     *
79     * Default implementation does nothing.
80     */
81    public void close() {
82    }
83
84    private HashSet<String> loadResourceStringSet(int res) {
85        HashSet<String> defaultCorpora = new HashSet<String>();
86        try {
87            String[] corpora = mContext.getResources().getStringArray(res);
88            for (String corpus : corpora) {
89                defaultCorpora.add(corpus);
90            }
91            return defaultCorpora;
92        } catch (Resources.NotFoundException ex) {
93            Log.e(TAG, "Could not load resource string set", ex);
94            return defaultCorpora;
95        }
96    }
97
98    /**
99     * Checks if we trust the given source not to be spammy.
100     */
101    public synchronized boolean isCorpusEnabledByDefault(String corpusName) {
102        if (mDefaultCorpora == null) {
103            mDefaultCorpora = loadResourceStringSet(R.array.default_corpora);
104        }
105        return mDefaultCorpora.contains(corpusName);
106    }
107
108    /**
109     * Checks if the given corpus should be hidden from the corpus selection dialog.
110     */
111    public synchronized boolean isCorpusHidden(String corpusName) {
112        if (mHiddenCorpora == null) {
113            mHiddenCorpora = loadResourceStringSet(R.array.hidden_corpora);
114        }
115        return mHiddenCorpora.contains(corpusName);
116    }
117
118    /**
119     * The number of promoted sources.
120     */
121    public int getNumPromotedSources() {
122        return NUM_PROMOTED_SOURCES;
123    }
124
125    /**
126     * The number of suggestions visible above the onscreen keyboard.
127     */
128    public int getNumSuggestionsAboveKeyboard() {
129        try {
130            // Get the list of default corpora from a resource, which allows vendor overlays.
131            return mContext.getResources().getInteger(R.integer.num_suggestions_above_keyboard);
132        } catch (Resources.NotFoundException ex) {
133            Log.e(TAG, "Could not load num_suggestions_above_keyboard", ex);
134            return NUM_SUGGESTIONS_ABOVE_KEYBOARD;
135        }
136    }
137
138    /**
139     * The maximum number of suggestions to promote.
140     */
141    public int getMaxPromotedSuggestions() {
142        return MAX_PROMOTED_SUGGESTIONS;
143    }
144
145    /**
146     * The number of results to ask each source for.
147     */
148    public int getMaxResultsPerSource() {
149        return MAX_RESULTS_PER_SOURCE;
150    }
151
152    /**
153     * The maximum number of shortcuts to show for the web source in All mode.
154     */
155    public int getMaxShortcutsPerWebSource() {
156        return MAX_SHORTCUTS_PER_WEB_SOURCE;
157    }
158
159    /**
160     * The maximum number of shortcuts to show for each non-web source in All mode.
161     */
162    public int getMaxShortcutsPerNonWebSource() {
163        return MAX_SHORTCUTS_PER_NON_WEB_SOURCE;
164    }
165
166    /**
167     * The timeout for querying each source, in milliseconds.
168     */
169    public long getSourceTimeoutMillis() {
170        return SOURCE_TIMEOUT_MILLIS;
171    }
172
173    /**
174     * The priority of query threads.
175     *
176     * @return A thread priority, as defined in {@link Process}.
177     */
178    public int getQueryThreadPriority() {
179        return QUERY_THREAD_PRIORITY;
180    }
181
182    /**
183     * The maximum age of log data used for shortcuts.
184     */
185    public long getMaxStatAgeMillis(){
186        return MAX_STAT_AGE_MILLIS;
187    }
188
189    /**
190     * The minimum number of clicks needed to rank a source.
191     */
192    public int getMinClicksForSourceRanking(){
193        return MIN_CLICKS_FOR_SOURCE_RANKING;
194    }
195
196    /**
197     * The maximum number of shortcuts shown.
198     */
199    public int getMaxShortcutsReturned(){
200        return MAX_SHORTCUTS_RETURNED;
201    }
202
203    public int getNumWebCorpusThreads() {
204        return NUM_WEB_CORPUS_THREADS;
205    }
206
207    /**
208     * How often query latency should be logged.
209     *
210     * @return An integer in the range 0-1000. 0 means that no latency events
211     *         should be logged. 1000 means that all latency events should be logged.
212     */
213    public int getLatencyLogFrequency() {
214        return LATENCY_LOG_FREQUENCY;
215    }
216
217    /**
218     * The delay in milliseconds before suggestions are updated while typing.
219     * If a new character is typed before this timeout expires, the timeout is reset.
220     */
221    public long getTypingUpdateSuggestionsDelayMillis() {
222        return TYPING_SUGGESTIONS_UPDATE_DELAY_MILLIS;
223    }
224
225    /**
226     * The delay in milliseconds before corpus results are published.
227     * If a new result arrives before this timeout expires, the timeout is reset.
228     */
229    public long getPublishResultDelayMillis() {
230        return PUBLISH_RESULT_DELAY_MILLIS;
231    }
232
233    public boolean allowVoiceSearchHints() {
234        return true;
235    }
236}
237