SearchSettingsImpl.java revision 34955d44dddabfc672a26263363190f971c337a8
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.SearchManager;
20import android.content.Context;
21import android.content.Intent;
22import android.content.SharedPreferences;
23import android.util.Log;
24import android.view.Menu;
25import android.view.MenuInflater;
26import android.view.MenuItem;
27
28/**
29 * Manages user settings.
30 */
31public class SearchSettingsImpl implements SearchSettings {
32
33    private static final boolean DBG = false;
34    private static final String TAG = "QSB.SearchSettingsImpl";
35
36    // Name of the preferences file used to store search preference
37    public static final String PREFERENCES_NAME = "SearchSettings";
38
39    // Intent action that opens the "Searchable Items" preference
40    private static final String ACTION_SEARCHABLE_ITEMS =
41            "com.android.quicksearchbox.action.SEARCHABLE_ITEMS";
42
43    /**
44     * Preference key used for storing the index of the next voice search hint to show.
45     */
46    private static final String NEXT_VOICE_SEARCH_HINT_INDEX_PREF = "next_voice_search_hint";
47
48    /**
49     * Preference key used to store the time at which the first voice search hint was displayed.
50     */
51    private static final String FIRST_VOICE_HINT_DISPLAY_TIME = "first_voice_search_hint_time";
52
53    /**
54     * Preference key for the version of voice search we last got hints from.
55     */
56    private static final String LAST_SEEN_VOICE_SEARCH_VERSION = "voice_search_version";
57
58    /**
59     * Prefix of per-corpus enable preference
60     */
61    private static final String CORPUS_ENABLED_PREF_PREFIX = "enable_corpus_";
62
63    private final Context mContext;
64
65    private final Config mConfig;
66
67    public SearchSettingsImpl(Context context, Config config) {
68        mContext = context;
69        mConfig = config;
70    }
71
72    protected Context getContext() {
73        return mContext;
74    }
75
76    protected Config getConfig() {
77        return mConfig;
78    }
79
80    public void upgradeSettingsIfNeeded() {
81    }
82
83    public Intent getSearchableItemsIntent() {
84        Intent intent = new Intent(ACTION_SEARCHABLE_ITEMS);
85        intent.setPackage(getContext().getPackageName());
86        return intent;
87    }
88
89    /**
90     * Gets the preference key of the preference for whether the given corpus
91     * is enabled. The preference is stored in the {@link #PREFERENCES_NAME}
92     * preferences file.
93     */
94    public static String getCorpusEnabledPreference(Corpus corpus) {
95        return CORPUS_ENABLED_PREF_PREFIX + corpus.getName();
96    }
97
98    public boolean isCorpusEnabled(Corpus corpus) {
99        boolean defaultEnabled = corpus.isCorpusDefaultEnabled();
100        String sourceEnabledPref = getCorpusEnabledPreference(corpus);
101        return getSearchPreferences().getBoolean(sourceEnabledPref, defaultEnabled);
102    }
103
104    protected SharedPreferences getSearchPreferences() {
105        return getContext().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
106    }
107
108    /**
109     * Informs our listeners about the updated settings data.
110     */
111    public void broadcastSettingsChanged() {
112        // We use a message broadcast since the listeners could be in multiple processes.
113        Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS_CHANGED);
114        Log.i(TAG, "Broadcasting: " + intent);
115        getContext().sendBroadcast(intent);
116    }
117
118    public void addMenuItems(Menu menu) {
119        MenuInflater inflater = new MenuInflater(getContext());
120        inflater.inflate(R.menu.settings, menu);
121        MenuItem item = menu.findItem(R.id.menu_settings);
122        item.setIntent(getSearchSettingsIntent());
123    }
124
125    public void updateMenuItems(Menu menu) {
126    }
127
128    public Intent getSearchSettingsIntent() {
129        Intent settings = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS);
130        settings.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
131        settings.setPackage(getContext().getPackageName());
132        return settings;
133    }
134
135    public int getNextVoiceSearchHintIndex(int size) {
136            int i = getAndIncrementIntPreference(getSearchPreferences(),
137                    NEXT_VOICE_SEARCH_HINT_INDEX_PREF);
138            return i % size;
139    }
140
141    // TODO: Could this be made atomic to avoid races?
142    private static int getAndIncrementIntPreference(SharedPreferences prefs, String name) {
143        int i = prefs.getInt(name, 0);
144        prefs.edit().putInt(name, i + 1).commit();
145        return i;
146    }
147
148    public void resetVoiceSearchHintFirstSeenTime() {
149        getSearchPreferences().edit()
150                .putLong(FIRST_VOICE_HINT_DISPLAY_TIME, System.currentTimeMillis()).commit();
151    }
152
153    public boolean haveVoiceSearchHintsExpired(int currentVoiceSearchVersion) {
154        SharedPreferences prefs = getSearchPreferences();
155
156        if (currentVoiceSearchVersion != 0) {
157            long currentTime = System.currentTimeMillis();
158            int lastVoiceSearchVersion = prefs.getInt(LAST_SEEN_VOICE_SEARCH_VERSION, 0);
159            long firstHintTime = prefs.getLong(FIRST_VOICE_HINT_DISPLAY_TIME, 0);
160            if (firstHintTime == 0 || currentVoiceSearchVersion != lastVoiceSearchVersion) {
161                prefs.edit()
162                        .putInt(LAST_SEEN_VOICE_SEARCH_VERSION, currentVoiceSearchVersion)
163                        .putLong(FIRST_VOICE_HINT_DISPLAY_TIME, currentTime)
164                        .commit();
165                firstHintTime = currentTime;
166            }
167            if (currentTime - firstHintTime > getConfig().getVoiceSearchHintActivePeriod()) {
168                if (DBG) Log.d(TAG, "Voice seach hint period expired; not showing hints.");
169                return true;
170            } else {
171                return false;
172            }
173        } else {
174            if (DBG) Log.d(TAG, "Could not determine voice search version; not showing hints.");
175            return true;
176        }
177    }
178
179    public boolean allowWebSearchShortcuts() {
180        return true;
181    }
182
183}
184