blob: 0ffbb7d0aa59054cda18b6f1a386e137a2684364 [file] [log] [blame]
Karl Rosaen875d50a2009-04-23 19:00:21 -07001/*
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
Jeff Sharkey7a96c392012-11-15 14:01:46 -080017package com.android.server.search;
Karl Rosaen875d50a2009-04-23 19:00:21 -070018
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070019import android.app.AppGlobals;
Bjorn Bringert74708bb2009-04-28 11:26:52 +010020import android.app.SearchManager;
Bjorn Bringert2126aac2009-12-03 15:48:19 +000021import android.app.SearchableInfo;
Karl Rosaen875d50a2009-04-23 19:00:21 -070022import android.content.ComponentName;
23import android.content.Context;
24import android.content.Intent;
25import android.content.pm.ActivityInfo;
Narayan Kamathee69ff42011-06-28 12:07:18 +010026import android.content.pm.ApplicationInfo;
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070027import android.content.pm.IPackageManager;
Karl Rosaen875d50a2009-04-23 19:00:21 -070028import android.content.pm.PackageManager;
29import android.content.pm.ResolveInfo;
Amith Yamasanif203aee2012-08-29 18:41:53 -070030import android.os.Binder;
Karl Rosaen875d50a2009-04-23 19:00:21 -070031import android.os.Bundle;
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070032import android.os.RemoteException;
Narayan Kamathee69ff42011-06-28 12:07:18 +010033import android.provider.Settings;
34import android.text.TextUtils;
Satish Sampathcbd8a242009-05-15 21:47:07 +010035import android.util.Log;
Karl Rosaen875d50a2009-04-23 19:00:21 -070036
Amith Yamasani64442c12012-10-07 08:17:46 -070037import java.io.FileDescriptor;
38import java.io.PrintWriter;
Karl Rosaen875d50a2009-04-23 19:00:21 -070039import java.util.ArrayList;
Narayan Kamathee69ff42011-06-28 12:07:18 +010040import java.util.Collections;
41import java.util.Comparator;
Karl Rosaen875d50a2009-04-23 19:00:21 -070042import java.util.HashMap;
43import java.util.List;
44
45/**
Satish Sampathf9acde22009-06-04 11:51:17 +010046 * This class maintains the information about all searchable activities.
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070047 * This is a hidden class.
Karl Rosaen875d50a2009-04-23 19:00:21 -070048 */
49public class Searchables {
50
Satish Sampathcbd8a242009-05-15 21:47:07 +010051 private static final String LOG_TAG = "Searchables";
52
Karl Rosaen875d50a2009-04-23 19:00:21 -070053 // static strings used for XML lookups, etc.
Satish Sampathf9acde22009-06-04 11:51:17 +010054 // TODO how should these be documented for the developer, in a more structured way than
Karl Rosaen875d50a2009-04-23 19:00:21 -070055 // the current long wordy javadoc in SearchManager.java ?
56 private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
57 private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
Satish Sampathf9acde22009-06-04 11:51:17 +010058
Karl Rosaen875d50a2009-04-23 19:00:21 -070059 private Context mContext;
Satish Sampathf9acde22009-06-04 11:51:17 +010060
Karl Rosaen875d50a2009-04-23 19:00:21 -070061 private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
62 private ArrayList<SearchableInfo> mSearchablesList = null;
Bjorn Bringert6d72e022009-04-29 14:56:12 +010063 private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
Narayan Kamathee69ff42011-06-28 12:07:18 +010064 // Contains all installed activities that handle the global search
65 // intent.
66 private List<ResolveInfo> mGlobalSearchActivities;
67 private ComponentName mCurrentGlobalSearchActivity = null;
Bjorn Bringert6cf7a322010-02-23 13:17:06 +000068 private ComponentName mWebSearchActivity = null;
Satish Sampathf9acde22009-06-04 11:51:17 +010069
Satish Sampath41282a32009-06-23 17:05:35 +010070 public static String GOOGLE_SEARCH_COMPONENT_NAME =
71 "com.android.googlesearch/.GoogleSearch";
72 public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
73 "com.google.android.providers.enhancedgooglesearch/.Launcher";
74
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070075 // Cache the package manager instance
Amith Yamasanif203aee2012-08-29 18:41:53 -070076 final private IPackageManager mPm;
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070077 // User for which this Searchables caches information
78 private int mUserId;
79
Karl Rosaen875d50a2009-04-23 19:00:21 -070080 /**
Satish Sampathf9acde22009-06-04 11:51:17 +010081 *
Karl Rosaen875d50a2009-04-23 19:00:21 -070082 * @param context Context to use for looking up activities etc.
83 */
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070084 public Searchables (Context context, int userId) {
Karl Rosaen875d50a2009-04-23 19:00:21 -070085 mContext = context;
Amith Yamasani5bb87cd2012-06-14 11:32:13 -070086 mUserId = userId;
Amith Yamasanif203aee2012-08-29 18:41:53 -070087 mPm = AppGlobals.getPackageManager();
Karl Rosaen875d50a2009-04-23 19:00:21 -070088 }
Satish Sampathf9acde22009-06-04 11:51:17 +010089
Karl Rosaen875d50a2009-04-23 19:00:21 -070090 /**
91 * Look up, or construct, based on the activity.
Satish Sampathf9acde22009-06-04 11:51:17 +010092 *
93 * The activities fall into three cases, based on meta-data found in
Karl Rosaen875d50a2009-04-23 19:00:21 -070094 * the manifest entry:
95 * <ol>
96 * <li>The activity itself implements search. This is indicated by the
97 * presence of a "android.app.searchable" meta-data attribute.
98 * The value is a reference to an XML file containing search information.</li>
99 * <li>A related activity implements search. This is indicated by the
100 * presence of a "android.app.default_searchable" meta-data attribute.
101 * The value is a string naming the activity implementing search. In this
102 * case the factory will "redirect" and return the searchable data.</li>
103 * <li>No searchability data is provided. We return null here and other
104 * code will insert the "default" (e.g. contacts) search.
Satish Sampathf9acde22009-06-04 11:51:17 +0100105 *
Karl Rosaen875d50a2009-04-23 19:00:21 -0700106 * TODO: cache the result in the map, and check the map first.
107 * TODO: it might make sense to implement the searchable reference as
108 * an application meta-data entry. This way we don't have to pepper each
109 * and every activity.
110 * TODO: can we skip the constructor step if it's a non-searchable?
Satish Sampathf9acde22009-06-04 11:51:17 +0100111 * TODO: does it make sense to plug the default into a slot here for
Karl Rosaen875d50a2009-04-23 19:00:21 -0700112 * automatic return? Probably not, but it's one way to do it.
113 *
Satish Sampathf9acde22009-06-04 11:51:17 +0100114 * @param activity The name of the current activity, or null if the
Karl Rosaen875d50a2009-04-23 19:00:21 -0700115 * activity does not define any explicit searchable metadata.
116 */
117 public SearchableInfo getSearchableInfo(ComponentName activity) {
118 // Step 1. Is the result already hashed? (case 1)
119 SearchableInfo result;
120 synchronized (this) {
121 result = mSearchablesMap.get(activity);
122 if (result != null) return result;
123 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100124
Karl Rosaen875d50a2009-04-23 19:00:21 -0700125 // Step 2. See if the current activity references a searchable.
126 // Note: Conceptually, this could be a while(true) loop, but there's
Satish Sampathf9acde22009-06-04 11:51:17 +0100127 // no point in implementing reference chaining here and risking a loop.
Karl Rosaen875d50a2009-04-23 19:00:21 -0700128 // References must point directly to searchable activities.
Satish Sampathf9acde22009-06-04 11:51:17 +0100129
Karl Rosaen875d50a2009-04-23 19:00:21 -0700130 ActivityInfo ai = null;
131 try {
Amith Yamasanif203aee2012-08-29 18:41:53 -0700132 ai = mPm.getActivityInfo(activity, PackageManager.GET_META_DATA, mUserId);
133 } catch (RemoteException re) {
134 Log.e(LOG_TAG, "Error getting activity info " + re);
135 return null;
136 }
137 String refActivityName = null;
Satish Sampathf9acde22009-06-04 11:51:17 +0100138
Amith Yamasanif203aee2012-08-29 18:41:53 -0700139 // First look for activity-specific reference
140 Bundle md = ai.metaData;
141 if (md != null) {
142 refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
143 }
144 // If not found, try for app-wide reference
145 if (refActivityName == null) {
146 md = ai.applicationInfo.metaData;
Karl Rosaen875d50a2009-04-23 19:00:21 -0700147 if (md != null) {
148 refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
149 }
Amith Yamasanif203aee2012-08-29 18:41:53 -0700150 }
151
152 // Irrespective of source, if a reference was found, follow it.
153 if (refActivityName != null)
154 {
155 // This value is deprecated, return null
156 if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
157 return null;
158 }
159 String pkg = activity.getPackageName();
160 ComponentName referredActivity;
161 if (refActivityName.charAt(0) == '.') {
162 referredActivity = new ComponentName(pkg, pkg + refActivityName);
163 } else {
164 referredActivity = new ComponentName(pkg, refActivityName);
Karl Rosaen875d50a2009-04-23 19:00:21 -0700165 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100166
Amith Yamasanif203aee2012-08-29 18:41:53 -0700167 // Now try the referred activity, and if found, cache
168 // it against the original name so we can skip the check
169 synchronized (this) {
170 result = mSearchablesMap.get(referredActivity);
171 if (result != null) {
172 mSearchablesMap.put(activity, result);
173 return result;
Karl Rosaen875d50a2009-04-23 19:00:21 -0700174 }
175 }
Karl Rosaen875d50a2009-04-23 19:00:21 -0700176 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100177
Karl Rosaen875d50a2009-04-23 19:00:21 -0700178 // Step 3. None found. Return null.
179 return null;
Satish Sampathf9acde22009-06-04 11:51:17 +0100180
Karl Rosaen875d50a2009-04-23 19:00:21 -0700181 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100182
Karl Rosaen875d50a2009-04-23 19:00:21 -0700183 /**
Satish Sampathf9acde22009-06-04 11:51:17 +0100184 * Builds an entire list (suitable for display) of
185 * activities that are searchable, by iterating the entire set of
186 * ACTION_SEARCH & ACTION_WEB_SEARCH intents.
187 *
Karl Rosaen875d50a2009-04-23 19:00:21 -0700188 * Also clears the hash of all activities -> searches which will
189 * refill as the user clicks "search".
Satish Sampathf9acde22009-06-04 11:51:17 +0100190 *
Karl Rosaen875d50a2009-04-23 19:00:21 -0700191 * This should only be done at startup and again if we know that the
192 * list has changed.
Satish Sampathf9acde22009-06-04 11:51:17 +0100193 *
Karl Rosaen875d50a2009-04-23 19:00:21 -0700194 * TODO: every activity that provides a ACTION_SEARCH intent should
195 * also provide searchability meta-data. There are a bunch of checks here
196 * that, if data is not found, silently skip to the next activity. This
197 * won't help a developer trying to figure out why their activity isn't
198 * showing up in the list, but an exception here is too rough. I would
199 * like to find a better notification mechanism.
Satish Sampathf9acde22009-06-04 11:51:17 +0100200 *
Karl Rosaen875d50a2009-04-23 19:00:21 -0700201 * TODO: sort the list somehow? UI choice.
202 */
203 public void buildSearchableList() {
Bjorn Bringert74708bb2009-04-28 11:26:52 +0100204 // These will become the new values at the end of the method
Satish Sampathf9acde22009-06-04 11:51:17 +0100205 HashMap<ComponentName, SearchableInfo> newSearchablesMap
Karl Rosaen875d50a2009-04-23 19:00:21 -0700206 = new HashMap<ComponentName, SearchableInfo>();
207 ArrayList<SearchableInfo> newSearchablesList
208 = new ArrayList<SearchableInfo>();
Bjorn Bringert6d72e022009-04-29 14:56:12 +0100209 ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
210 = new ArrayList<SearchableInfo>();
Karl Rosaen875d50a2009-04-23 19:00:21 -0700211
Satish Sampathf9acde22009-06-04 11:51:17 +0100212 // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
213 List<ResolveInfo> searchList;
Karl Rosaen875d50a2009-04-23 19:00:21 -0700214 final Intent intent = new Intent(Intent.ACTION_SEARCH);
Satish Sampathf9acde22009-06-04 11:51:17 +0100215
Amith Yamasani64442c12012-10-07 08:17:46 -0700216 long ident = Binder.clearCallingIdentity();
217 try {
218 searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA);
Satish Sampathf9acde22009-06-04 11:51:17 +0100219
Amith Yamasani64442c12012-10-07 08:17:46 -0700220 List<ResolveInfo> webSearchInfoList;
221 final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
222 webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
223
224 // analyze each one, generate a Searchables record, and record
225 if (searchList != null || webSearchInfoList != null) {
226 int search_count = (searchList == null ? 0 : searchList.size());
227 int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
228 int count = search_count + web_search_count;
229 for (int ii = 0; ii < count; ii++) {
230 // for each component, try to find metadata
231 ResolveInfo info = (ii < search_count)
232 ? searchList.get(ii)
233 : webSearchInfoList.get(ii - search_count);
234 ActivityInfo ai = info.activityInfo;
235 // Check first to avoid duplicate entries.
236 if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) {
237 SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai,
238 mUserId);
239 if (searchable != null) {
240 newSearchablesList.add(searchable);
241 newSearchablesMap.put(searchable.getSearchActivity(), searchable);
242 if (searchable.shouldIncludeInGlobalSearch()) {
243 newSearchablesInGlobalSearchList.add(searchable);
244 }
Karl Rosaen590f6342009-08-27 17:42:48 -0700245 }
Bjorn Bringert6d72e022009-04-29 14:56:12 +0100246 }
Karl Rosaen875d50a2009-04-23 19:00:21 -0700247 }
248 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100249
Amith Yamasani64442c12012-10-07 08:17:46 -0700250 List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities();
Narayan Kamathee69ff42011-06-28 12:07:18 +0100251
Amith Yamasani64442c12012-10-07 08:17:46 -0700252 // Find the global search activity
253 ComponentName newGlobalSearchActivity = findGlobalSearchActivity(
254 newGlobalSearchActivities);
Satish Sampathf9acde22009-06-04 11:51:17 +0100255
Amith Yamasani64442c12012-10-07 08:17:46 -0700256 // Find the web search activity
257 ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity);
Satish Sampathf9acde22009-06-04 11:51:17 +0100258
Amith Yamasani64442c12012-10-07 08:17:46 -0700259 // Store a consistent set of new values
260 synchronized (this) {
261 mSearchablesMap = newSearchablesMap;
262 mSearchablesList = newSearchablesList;
263 mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
264 mGlobalSearchActivities = newGlobalSearchActivities;
265 mCurrentGlobalSearchActivity = newGlobalSearchActivity;
266 mWebSearchActivity = newWebSearchActivity;
267 }
268 } finally {
269 Binder.restoreCallingIdentity(ident);
Karl Rosaen875d50a2009-04-23 19:00:21 -0700270 }
271 }
Amith Yamasani64442c12012-10-07 08:17:46 -0700272
Satish Sampathf9acde22009-06-04 11:51:17 +0100273 /**
Narayan Kamathee69ff42011-06-28 12:07:18 +0100274 * Returns a sorted list of installed search providers as per
275 * the following heuristics:
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000276 *
Narayan Kamathee69ff42011-06-28 12:07:18 +0100277 * (a) System apps are given priority over non system apps.
278 * (b) Among system apps and non system apps, the relative ordering
279 * is defined by their declared priority.
Satish Sampathf9acde22009-06-04 11:51:17 +0100280 */
Narayan Kamathee69ff42011-06-28 12:07:18 +0100281 private List<ResolveInfo> findGlobalSearchActivities() {
282 // Step 1 : Query the package manager for a list
283 // of activities that can handle the GLOBAL_SEARCH intent.
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000284 Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000285 List<ResolveInfo> activities =
Amith Yamasani5bb87cd2012-06-14 11:32:13 -0700286 queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
Narayan Kamathee69ff42011-06-28 12:07:18 +0100287 if (activities != null && !activities.isEmpty()) {
288 // Step 2: Rank matching activities according to our heuristics.
289 Collections.sort(activities, GLOBAL_SEARCH_RANKER);
290 }
291
292 return activities;
293 }
294
295 /**
296 * Finds the global search activity.
297 */
298 private ComponentName findGlobalSearchActivity(List<ResolveInfo> installed) {
299 // Fetch the global search provider from the system settings,
300 // and if it's still installed, return it.
301 final String searchProviderSetting = getGlobalSearchProviderSetting();
302 if (!TextUtils.isEmpty(searchProviderSetting)) {
303 final ComponentName globalSearchComponent = ComponentName.unflattenFromString(
304 searchProviderSetting);
305 if (globalSearchComponent != null && isInstalled(globalSearchComponent)) {
306 return globalSearchComponent;
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000307 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100308 }
Narayan Kamathee69ff42011-06-28 12:07:18 +0100309
310 return getDefaultGlobalSearchProvider(installed);
311 }
312
313 /**
314 * Checks whether the global search provider with a given
315 * component name is installed on the system or not. This deals with
316 * cases such as the removal of an installed provider.
317 */
318 private boolean isInstalled(ComponentName globalSearch) {
319 Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
320 intent.setComponent(globalSearch);
321
Amith Yamasani5bb87cd2012-06-14 11:32:13 -0700322 List<ResolveInfo> activities = queryIntentActivities(intent,
323 PackageManager.MATCH_DEFAULT_ONLY);
Narayan Kamathee69ff42011-06-28 12:07:18 +0100324 if (activities != null && !activities.isEmpty()) {
325 return true;
326 }
327
328 return false;
329 }
330
331 private static final Comparator<ResolveInfo> GLOBAL_SEARCH_RANKER =
332 new Comparator<ResolveInfo>() {
333 @Override
334 public int compare(ResolveInfo lhs, ResolveInfo rhs) {
335 if (lhs == rhs) {
336 return 0;
337 }
338 boolean lhsSystem = isSystemApp(lhs);
339 boolean rhsSystem = isSystemApp(rhs);
340
341 if (lhsSystem && !rhsSystem) {
342 return -1;
343 } else if (rhsSystem && !lhsSystem) {
344 return 1;
345 } else {
346 // Either both system engines, or both non system
347 // engines.
348 //
349 // Note, this isn't a typo. Higher priority numbers imply
350 // higher priority, but are "lower" in the sort order.
351 return rhs.priority - lhs.priority;
352 }
353 }
354 };
355
356 /**
357 * @return true iff. the resolve info corresponds to a system application.
358 */
359 private static final boolean isSystemApp(ResolveInfo res) {
360 return (res.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
361 }
362
363 /**
364 * Returns the highest ranked search provider as per the
365 * ranking defined in {@link #getGlobalSearchActivities()}.
366 */
367 private ComponentName getDefaultGlobalSearchProvider(List<ResolveInfo> providerList) {
368 if (providerList != null && !providerList.isEmpty()) {
369 ActivityInfo ai = providerList.get(0).activityInfo;
370 return new ComponentName(ai.packageName, ai.name);
371 }
372
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000373 Log.w(LOG_TAG, "No global search activity found");
374 return null;
Satish Sampathf9acde22009-06-04 11:51:17 +0100375 }
376
Narayan Kamathee69ff42011-06-28 12:07:18 +0100377 private String getGlobalSearchProviderSetting() {
378 return Settings.Secure.getString(mContext.getContentResolver(),
379 Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY);
380 }
381
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000382 /**
383 * Finds the web search activity.
384 *
385 * Only looks in the package of the global search activity.
386 */
387 private ComponentName findWebSearchActivity(ComponentName globalSearchActivity) {
388 if (globalSearchActivity == null) {
389 return null;
Satish Sampathf9acde22009-06-04 11:51:17 +0100390 }
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000391 Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
392 intent.setPackage(globalSearchActivity.getPackageName());
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000393 List<ResolveInfo> activities =
Amith Yamasani5bb87cd2012-06-14 11:32:13 -0700394 queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
Narayan Kamathee69ff42011-06-28 12:07:18 +0100395
396 if (activities != null && !activities.isEmpty()) {
397 ActivityInfo ai = activities.get(0).activityInfo;
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000398 // TODO: do some sanity checks here?
399 return new ComponentName(ai.packageName, ai.name);
400 }
401 Log.w(LOG_TAG, "No web search activity found");
402 return null;
Satish Sampathf9acde22009-06-04 11:51:17 +0100403 }
404
Amith Yamasani5bb87cd2012-06-14 11:32:13 -0700405 private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
Amith Yamasani5bb87cd2012-06-14 11:32:13 -0700406 List<ResolveInfo> activities = null;
407 try {
408 activities =
409 mPm.queryIntentActivities(intent,
410 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
411 flags, mUserId);
412 } catch (RemoteException re) {
413 // Local call
414 }
415 return activities;
416 }
417
Karl Rosaen875d50a2009-04-23 19:00:21 -0700418 /**
419 * Returns the list of searchable activities.
420 */
421 public synchronized ArrayList<SearchableInfo> getSearchablesList() {
422 ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList);
423 return result;
424 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100425
Bjorn Bringert6d72e022009-04-29 14:56:12 +0100426 /**
427 * Returns a list of the searchable activities that can be included in global search.
428 */
429 public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() {
430 return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList);
431 }
Satish Sampathf9acde22009-06-04 11:51:17 +0100432
433 /**
Narayan Kamathee69ff42011-06-28 12:07:18 +0100434 * Returns a list of activities that handle the global search intent.
435 */
436 public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() {
437 return new ArrayList<ResolveInfo>(mGlobalSearchActivities);
438 }
439
440 /**
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000441 * Gets the name of the global search activity.
Satish Sampathf9acde22009-06-04 11:51:17 +0100442 */
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000443 public synchronized ComponentName getGlobalSearchActivity() {
Narayan Kamathee69ff42011-06-28 12:07:18 +0100444 return mCurrentGlobalSearchActivity;
Satish Sampathf9acde22009-06-04 11:51:17 +0100445 }
446
447 /**
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000448 * Gets the name of the web search activity.
Satish Sampathf9acde22009-06-04 11:51:17 +0100449 */
Bjorn Bringert6cf7a322010-02-23 13:17:06 +0000450 public synchronized ComponentName getWebSearchActivity() {
451 return mWebSearchActivity;
Satish Sampathf9acde22009-06-04 11:51:17 +0100452 }
Amith Yamasani64442c12012-10-07 08:17:46 -0700453
454 void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
455 pw.println("Searchable authorities:");
456 synchronized (this) {
457 if (mSearchablesList != null) {
458 for (SearchableInfo info: mSearchablesList) {
459 pw.print(" "); pw.println(info.getSuggestAuthority());
460 }
461 }
462 }
463 }
Karl Rosaen875d50a2009-04-23 19:00:21 -0700464}