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.SearchManager;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.SharedPreferences;
     23 import android.content.SharedPreferences.Editor;
     24 import android.util.Log;
     25 
     26 import com.android.common.SharedPreferencesCompat;
     27 
     28 /**
     29  * Manages user settings.
     30  */
     31 public 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     /**
     40      * Preference key used for storing the index of the next voice search hint to show.
     41      */
     42     private static final String NEXT_VOICE_SEARCH_HINT_INDEX_PREF = "next_voice_search_hint";
     43 
     44     /**
     45      * Preference key used to store the time at which the first voice search hint was displayed.
     46      */
     47     private static final String FIRST_VOICE_HINT_DISPLAY_TIME = "first_voice_search_hint_time";
     48 
     49     /**
     50      * Preference key for the version of voice search we last got hints from.
     51      */
     52     private static final String LAST_SEEN_VOICE_SEARCH_VERSION = "voice_search_version";
     53 
     54     /**
     55      * Preference key for storing whether searches always go to google.com. Public
     56      * so that it can be used by PreferenceControllers.
     57      */
     58     public static final String USE_GOOGLE_COM_PREF = "use_google_com";
     59 
     60     /**
     61      * Preference key for the base search URL. This value is normally set by
     62      * a SearchBaseUrlHelper instance. Public so classes can listen to changes
     63      * on this key.
     64      */
     65     public static final String SEARCH_BASE_DOMAIN_PREF = "search_base_domain";
     66 
     67     /**
     68      * This is the time at which the base URL was stored, and is set using
     69      * @link{System.currentTimeMillis()}.
     70      */
     71     private static final String SEARCH_BASE_DOMAIN_APPLY_TIME = "search_base_domain_apply_time";
     72 
     73     private final Context mContext;
     74 
     75     private final Config mConfig;
     76 
     77     public SearchSettingsImpl(Context context, Config config) {
     78         mContext = context;
     79         mConfig = config;
     80     }
     81 
     82     protected Context getContext() {
     83         return mContext;
     84     }
     85 
     86     protected Config getConfig() {
     87         return mConfig;
     88     }
     89 
     90     @Override
     91     public void upgradeSettingsIfNeeded() {
     92     }
     93 
     94     public SharedPreferences getSearchPreferences() {
     95         return getContext().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
     96     }
     97 
     98     protected void storeBoolean(String name, boolean value) {
     99         SharedPreferencesCompat.apply(getSearchPreferences().edit().putBoolean(name, value));
    100     }
    101 
    102     protected void storeInt(String name, int value) {
    103         SharedPreferencesCompat.apply(getSearchPreferences().edit().putInt(name, value));
    104     }
    105 
    106     protected void storeLong(String name, long value) {
    107         SharedPreferencesCompat.apply(getSearchPreferences().edit().putLong(name, value));
    108     }
    109 
    110     protected void storeString(String name, String value) {
    111         SharedPreferencesCompat.apply(getSearchPreferences().edit().putString(name, value));
    112     }
    113 
    114     protected void removePref(String name) {
    115         SharedPreferencesCompat.apply(getSearchPreferences().edit().remove(name));
    116     }
    117 
    118     /**
    119      * Informs our listeners about the updated settings data.
    120      */
    121     @Override
    122     public void broadcastSettingsChanged() {
    123         // We use a message broadcast since the listeners could be in multiple processes.
    124         Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCH_SETTINGS_CHANGED);
    125         Log.i(TAG, "Broadcasting: " + intent);
    126         getContext().sendBroadcast(intent);
    127     }
    128 
    129     @Override
    130     public int getNextVoiceSearchHintIndex(int size) {
    131             int i = getAndIncrementIntPreference(getSearchPreferences(),
    132                     NEXT_VOICE_SEARCH_HINT_INDEX_PREF);
    133             return i % size;
    134     }
    135 
    136     // TODO: Could this be made atomic to avoid races?
    137     private int getAndIncrementIntPreference(SharedPreferences prefs, String name) {
    138         int i = prefs.getInt(name, 0);
    139         storeInt(name, i + 1);
    140         return i;
    141     }
    142 
    143     @Override
    144     public void resetVoiceSearchHintFirstSeenTime() {
    145         storeLong(FIRST_VOICE_HINT_DISPLAY_TIME, System.currentTimeMillis());
    146     }
    147 
    148     @Override
    149     public boolean haveVoiceSearchHintsExpired(int currentVoiceSearchVersion) {
    150         SharedPreferences prefs = getSearchPreferences();
    151 
    152         if (currentVoiceSearchVersion != 0) {
    153             long currentTime = System.currentTimeMillis();
    154             int lastVoiceSearchVersion = prefs.getInt(LAST_SEEN_VOICE_SEARCH_VERSION, 0);
    155             long firstHintTime = prefs.getLong(FIRST_VOICE_HINT_DISPLAY_TIME, 0);
    156             if (firstHintTime == 0 || currentVoiceSearchVersion != lastVoiceSearchVersion) {
    157                 SharedPreferencesCompat.apply(prefs.edit()
    158                         .putInt(LAST_SEEN_VOICE_SEARCH_VERSION, currentVoiceSearchVersion)
    159                         .putLong(FIRST_VOICE_HINT_DISPLAY_TIME, currentTime));
    160                 firstHintTime = currentTime;
    161             }
    162             if (currentTime - firstHintTime > getConfig().getVoiceSearchHintActivePeriod()) {
    163                 if (DBG) Log.d(TAG, "Voice seach hint period expired; not showing hints.");
    164                 return true;
    165             } else {
    166                 return false;
    167             }
    168         } else {
    169             if (DBG) Log.d(TAG, "Could not determine voice search version; not showing hints.");
    170             return true;
    171         }
    172     }
    173 
    174     /**
    175      * @return true if user searches should always be based at google.com, false
    176      *     otherwise.
    177      */
    178     @Override
    179     public boolean shouldUseGoogleCom() {
    180         // Note that this preserves the old behaviour of using google.com
    181         // for searches, with the gl= parameter set.
    182         return getSearchPreferences().getBoolean(USE_GOOGLE_COM_PREF, true);
    183     }
    184 
    185     @Override
    186     public void setUseGoogleCom(boolean useGoogleCom) {
    187         storeBoolean(USE_GOOGLE_COM_PREF, useGoogleCom);
    188     }
    189 
    190     @Override
    191     public long getSearchBaseDomainApplyTime() {
    192         return getSearchPreferences().getLong(SEARCH_BASE_DOMAIN_APPLY_TIME, -1);
    193     }
    194 
    195     @Override
    196     public String getSearchBaseDomain() {
    197         // Note that the only time this will return null is on the first run
    198         // of the app, or when settings have been cleared. Callers should
    199         // ideally check that getSearchBaseDomainApplyTime() is not -1 before
    200         // calling this function.
    201         return getSearchPreferences().getString(SEARCH_BASE_DOMAIN_PREF, null);
    202     }
    203 
    204     @Override
    205     public void setSearchBaseDomain(String searchBaseUrl) {
    206         Editor sharedPrefEditor = getSearchPreferences().edit();
    207         sharedPrefEditor.putString(SEARCH_BASE_DOMAIN_PREF, searchBaseUrl);
    208         sharedPrefEditor.putLong(SEARCH_BASE_DOMAIN_APPLY_TIME, System.currentTimeMillis());
    209 
    210         SharedPreferencesCompat.apply(sharedPrefEditor);
    211     }
    212 }
    213