SearchManagerService.java revision 9bc75cb9c23e5df528a28acc1fbbb4b5be51c33d
1/* 2 * Copyright (C) 2007 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 android.server.search; 18 19import android.app.ISearchManager; 20import android.app.ISearchManagerCallback; 21import android.app.SearchManager; 22import android.content.BroadcastReceiver; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.os.Bundle; 28import android.os.Handler; 29import android.util.Log; 30 31import java.util.List; 32 33/** 34 * The search manager service handles the search UI, and maintains a registry of searchable 35 * activities. 36 */ 37public class SearchManagerService extends ISearchManager.Stub { 38 39 // general debugging support 40 private static final String TAG = "SearchManagerService"; 41 private static final boolean DBG = false; 42 43 // Context that the service is running in. 44 private final Context mContext; 45 46 // This field is initialized in ensureSearchablesCreated(), and then never modified. 47 // Only accessed by ensureSearchablesCreated() and getSearchables() 48 private Searchables mSearchables; 49 50 // This field is initialized in ensureSearchDialogCreated(), and then never modified. 51 // Only accessed by ensureSearchDialogCreated() and getSearchDialog() 52 private SearchDialogWrapper mSearchDialog; 53 54 /** 55 * Initializes the Search Manager service in the provided system context. 56 * Only one instance of this object should be created! 57 * 58 * @param context to use for accessing DB, window manager, etc. 59 */ 60 public SearchManagerService(Context context) { 61 mContext = context; 62 // call initialize() after all pending actions on the main system thread have finished 63 new Handler().post(new Runnable() { 64 public void run() { 65 initialize(); 66 } 67 }); 68 } 69 70 /** 71 * Initializes the list of searchable activities and the search UI. 72 */ 73 void initialize() { 74 ensureSearchablesCreated(); 75 ensureSearchDialogCreated(); 76 } 77 78 private synchronized void ensureSearchablesCreated() { 79 if (mSearchables != null) return; // already created 80 81 mSearchables = new Searchables(mContext); 82 mSearchables.buildSearchableList(); 83 84 IntentFilter packageFilter = new IntentFilter(); 85 packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 86 packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 87 packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 88 packageFilter.addDataScheme("package"); 89 mContext.registerReceiver(mPackageChangedReceiver, packageFilter); 90 } 91 92 private synchronized void ensureSearchDialogCreated() { 93 if (mSearchDialog != null) return; 94 95 mSearchDialog = new SearchDialogWrapper(mContext); 96 } 97 98 private synchronized Searchables getSearchables() { 99 ensureSearchablesCreated(); 100 return mSearchables; 101 } 102 103 private synchronized SearchDialogWrapper getSearchDialog() { 104 ensureSearchDialogCreated(); 105 return mSearchDialog; 106 } 107 108 /** 109 * Refreshes the "searchables" list when packages are added/removed. 110 */ 111 private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() { 112 @Override 113 public void onReceive(Context context, Intent intent) { 114 String action = intent.getAction(); 115 116 if (Intent.ACTION_PACKAGE_ADDED.equals(action) || 117 Intent.ACTION_PACKAGE_REMOVED.equals(action) || 118 Intent.ACTION_PACKAGE_CHANGED.equals(action)) { 119 if (DBG) Log.d(TAG, "Got " + action); 120 // Dismiss search dialog, since the search context may no longer be valid 121 getSearchDialog().stopSearch(); 122 // Update list of searchable activities 123 getSearchables().buildSearchableList(); 124 broadcastSearchablesChanged(); 125 } 126 } 127 }; 128 129 /** 130 * Informs all listeners that the list of searchables has been updated. 131 */ 132 void broadcastSearchablesChanged() { 133 mContext.sendBroadcast( 134 new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED)); 135 } 136 137 // 138 // Searchable activities API 139 // 140 141 /** 142 * Returns the SearchableInfo for a given activity. 143 * 144 * @param launchActivity The activity from which we're launching this search. 145 * @param globalSearch If false, this will only launch the search that has been specifically 146 * defined by the application (which is usually defined as a local search). If no default 147 * search is defined in the current application or activity, no search will be launched. 148 * If true, this will always launch a platform-global (e.g. web-based) search instead. 149 * @return Returns a SearchableInfo record describing the parameters of the search, 150 * or null if no searchable metadata was available. 151 */ 152 public SearchableInfo getSearchableInfo(final ComponentName launchActivity, 153 final boolean globalSearch) { 154 if (globalSearch) { 155 return getSearchables().getDefaultSearchable(); 156 } else { 157 if (launchActivity == null) { 158 Log.e(TAG, "getSearchableInfo(), activity == null"); 159 return null; 160 } 161 return getSearchables().getSearchableInfo(launchActivity); 162 } 163 } 164 165 /** 166 * Returns a list of the searchable activities that can be included in global search. 167 */ 168 public List<SearchableInfo> getSearchablesInGlobalSearch() { 169 return getSearchables().getSearchablesInGlobalSearchList(); 170 } 171 172 /** 173 * Returns a list of the searchable activities that handle web searches. 174 * Can be called from any thread. 175 */ 176 public List<SearchableInfo> getSearchablesForWebSearch() { 177 return getSearchables().getSearchablesForWebSearchList(); 178 } 179 180 /** 181 * Returns the default searchable activity for web searches. 182 * Can be called from any thread. 183 */ 184 public SearchableInfo getDefaultSearchableForWebSearch() { 185 return getSearchables().getDefaultSearchableForWebSearch(); 186 } 187 188 /** 189 * Sets the default searchable activity for web searches. 190 * Can be called from any thread. 191 */ 192 public void setDefaultWebSearch(final ComponentName component) { 193 getSearchables().setDefaultWebSearch(component); 194 broadcastSearchablesChanged(); 195 } 196 197 // Search UI API 198 199 /** 200 * Launches the search UI. Can be called from any thread. 201 * 202 * @see SearchManager#startSearch(String, boolean, ComponentName, Bundle, boolean) 203 */ 204 public void startSearch(String initialQuery, 205 boolean selectInitialQuery, 206 ComponentName launchActivity, 207 Bundle appSearchData, 208 boolean globalSearch, 209 ISearchManagerCallback searchManagerCallback) { 210 getSearchDialog().startSearch(initialQuery, 211 selectInitialQuery, 212 launchActivity, 213 appSearchData, 214 globalSearch, 215 searchManagerCallback); 216 } 217 218 /** 219 * Cancels the search dialog. Can be called from any thread. 220 */ 221 public void stopSearch() { 222 getSearchDialog().stopSearch(); 223 } 224 225} 226