Searchables.java revision 5bb87cd9b81506b0c25d3f9184e406762a9e9d9c
1875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen/* 2875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Copyright (C) 2009 The Android Open Source Project 3875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 4875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Licensed under the Apache License, Version 2.0 (the "License"); 5875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * you may not use this file except in compliance with the License. 6875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * You may obtain a copy of the License at 7875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 8875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * http://www.apache.org/licenses/LICENSE-2.0 9875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 10875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Unless required by applicable law or agreed to in writing, software 11875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * distributed under the License is distributed on an "AS IS" BASIS, 12875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * See the License for the specific language governing permissions and 14875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * limitations under the License. 15875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 16875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 17875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenpackage android.server.search; 18875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 195bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.app.AppGlobals; 2074708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringertimport android.app.SearchManager; 212126aac7f992b57fc52141a8bd09fa7a45ac2509Bjorn Bringertimport android.app.SearchableInfo; 22875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.ComponentName; 23875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.Context; 24875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.Intent; 25875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.pm.ActivityInfo; 26ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.pm.ApplicationInfo; 275bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.content.pm.IPackageManager; 28875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.pm.PackageManager; 29875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.content.pm.ResolveInfo; 30875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.os.Bundle; 315bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.os.RemoteException; 32ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.provider.Settings; 33ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.text.TextUtils; 34cbd8a246f86704fb348247245904a9f114f11280Satish Sampathimport android.util.Log; 35875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 36875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport java.util.ArrayList; 37ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport java.util.Collections; 38ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport java.util.Comparator; 39875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport java.util.HashMap; 40875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport java.util.List; 41875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 42875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen/** 43f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * This class maintains the information about all searchable activities. 445bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani * This is a hidden class. 45875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 46875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenpublic class Searchables { 47875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 48cbd8a246f86704fb348247245904a9f114f11280Satish Sampath private static final String LOG_TAG = "Searchables"; 49cbd8a246f86704fb348247245904a9f114f11280Satish Sampath 50875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // static strings used for XML lookups, etc. 51f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // TODO how should these be documented for the developer, in a more structured way than 52875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // the current long wordy javadoc in SearchManager.java ? 53875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable"; 54875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*"; 55f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 56875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private Context mContext; 57f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 58875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null; 59875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private ArrayList<SearchableInfo> mSearchablesList = null; 606d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null; 61ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Contains all installed activities that handle the global search 62ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // intent. 63ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private List<ResolveInfo> mGlobalSearchActivities; 64ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ComponentName mCurrentGlobalSearchActivity = null; 656cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert private ComponentName mWebSearchActivity = null; 66f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 6741282a35568b51270440450c46bb31aa00e52caaSatish Sampath public static String GOOGLE_SEARCH_COMPONENT_NAME = 6841282a35568b51270440450c46bb31aa00e52caaSatish Sampath "com.android.googlesearch/.GoogleSearch"; 6941282a35568b51270440450c46bb31aa00e52caaSatish Sampath public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME = 7041282a35568b51270440450c46bb31aa00e52caaSatish Sampath "com.google.android.providers.enhancedgooglesearch/.Launcher"; 7141282a35568b51270440450c46bb31aa00e52caaSatish Sampath 725bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // Cache the package manager instance 735bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani private IPackageManager mPm; 745bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // User for which this Searchables caches information 755bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani private int mUserId; 765bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani 77875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 78f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 79875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param context Context to use for looking up activities etc. 80875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 815bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani public Searchables (Context context, int userId) { 82875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mContext = context; 835bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani mUserId = userId; 84875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 85f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 86875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 87875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Look up, or construct, based on the activity. 88f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 89f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * The activities fall into three cases, based on meta-data found in 90875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * the manifest entry: 91875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <ol> 92875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <li>The activity itself implements search. This is indicated by the 93875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * presence of a "android.app.searchable" meta-data attribute. 94875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * The value is a reference to an XML file containing search information.</li> 95875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <li>A related activity implements search. This is indicated by the 96875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * presence of a "android.app.default_searchable" meta-data attribute. 97875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * The value is a string naming the activity implementing search. In this 98875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * case the factory will "redirect" and return the searchable data.</li> 99875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <li>No searchability data is provided. We return null here and other 100875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * code will insert the "default" (e.g. contacts) search. 101f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 102875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: cache the result in the map, and check the map first. 103875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: it might make sense to implement the searchable reference as 104875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * an application meta-data entry. This way we don't have to pepper each 105875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * and every activity. 106875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: can we skip the constructor step if it's a non-searchable? 107f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * TODO: does it make sense to plug the default into a slot here for 108875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * automatic return? Probably not, but it's one way to do it. 109875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 110f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * @param activity The name of the current activity, or null if the 111875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * activity does not define any explicit searchable metadata. 112875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 113875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public SearchableInfo getSearchableInfo(ComponentName activity) { 114875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Step 1. Is the result already hashed? (case 1) 115875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen SearchableInfo result; 116875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen synchronized (this) { 117875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen result = mSearchablesMap.get(activity); 118875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (result != null) return result; 119875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 120f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 121875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Step 2. See if the current activity references a searchable. 122875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Note: Conceptually, this could be a while(true) loop, but there's 123f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // no point in implementing reference chaining here and risking a loop. 124875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // References must point directly to searchable activities. 125f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 126875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ActivityInfo ai = null; 127875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen try { 128875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ai = mContext.getPackageManager(). 129875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen getActivityInfo(activity, PackageManager.GET_META_DATA ); 130875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen String refActivityName = null; 131f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 132875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // First look for activity-specific reference 133875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen Bundle md = ai.metaData; 134875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (md != null) { 135875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); 136875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 137875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // If not found, try for app-wide reference 138875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (refActivityName == null) { 139875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen md = ai.applicationInfo.metaData; 140875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (md != null) { 141875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); 142875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 143875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 144f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 145875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Irrespective of source, if a reference was found, follow it. 146875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (refActivityName != null) 147875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen { 1486cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert // This value is deprecated, return null 149875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) { 1506cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 151875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 152875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen String pkg = activity.getPackageName(); 153875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ComponentName referredActivity; 154875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (refActivityName.charAt(0) == '.') { 155875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen referredActivity = new ComponentName(pkg, pkg + refActivityName); 156875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } else { 157875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen referredActivity = new ComponentName(pkg, refActivityName); 158875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 159875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 160875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Now try the referred activity, and if found, cache 161875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // it against the original name so we can skip the check 162875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen synchronized (this) { 163875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen result = mSearchablesMap.get(referredActivity); 164875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (result != null) { 165875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mSearchablesMap.put(activity, result); 166875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return result; 167875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 168875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 169875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 170875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } catch (PackageManager.NameNotFoundException e) { 171875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // case 3: no metadata 172875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 173f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 174875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Step 3. None found. Return null. 175875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return null; 176f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 177875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 178f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 179875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 180f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * Builds an entire list (suitable for display) of 181f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * activities that are searchable, by iterating the entire set of 182f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * ACTION_SEARCH & ACTION_WEB_SEARCH intents. 183f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 184875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Also clears the hash of all activities -> searches which will 185875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * refill as the user clicks "search". 186f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 187875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * This should only be done at startup and again if we know that the 188875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * list has changed. 189f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 190875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: every activity that provides a ACTION_SEARCH intent should 191875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * also provide searchability meta-data. There are a bunch of checks here 192875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * that, if data is not found, silently skip to the next activity. This 193875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * won't help a developer trying to figure out why their activity isn't 194875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * showing up in the list, but an exception here is too rough. I would 195875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * like to find a better notification mechanism. 196f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 197875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: sort the list somehow? UI choice. 198875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 199875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public void buildSearchableList() { 20074708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert // These will become the new values at the end of the method 201f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath HashMap<ComponentName, SearchableInfo> newSearchablesMap 202875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen = new HashMap<ComponentName, SearchableInfo>(); 203875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ArrayList<SearchableInfo> newSearchablesList 204875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen = new ArrayList<SearchableInfo>(); 2056d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert ArrayList<SearchableInfo> newSearchablesInGlobalSearchList 2066d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert = new ArrayList<SearchableInfo>(); 207875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 208f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers. 209f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath List<ResolveInfo> searchList; 210875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen final Intent intent = new Intent(Intent.ACTION_SEARCH); 2115bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA); 212f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 213f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath List<ResolveInfo> webSearchInfoList; 214f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH); 2155bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA); 216f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 217875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // analyze each one, generate a Searchables record, and record 218f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath if (searchList != null || webSearchInfoList != null) { 219f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath int search_count = (searchList == null ? 0 : searchList.size()); 220f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size()); 221f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath int count = search_count + web_search_count; 222875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen for (int ii = 0; ii < count; ii++) { 223875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // for each component, try to find metadata 224f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath ResolveInfo info = (ii < search_count) 225f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath ? searchList.get(ii) 226f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath : webSearchInfoList.get(ii - search_count); 227875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ActivityInfo ai = info.activityInfo; 228f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // Check first to avoid duplicate entries. 229590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) { 230590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai); 231590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen if (searchable != null) { 232590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen newSearchablesList.add(searchable); 233590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen newSearchablesMap.put(searchable.getSearchActivity(), searchable); 234590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen if (searchable.shouldIncludeInGlobalSearch()) { 235590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen newSearchablesInGlobalSearchList.add(searchable); 236590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen } 2376d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert } 238875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 239875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 240875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 241f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 242ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities(); 243ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 2446cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert // Find the global search activity 245ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath ComponentName newGlobalSearchActivity = findGlobalSearchActivity( 246ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath newGlobalSearchActivities); 247cbd8a246f86704fb348247245904a9f114f11280Satish Sampath 2486cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert // Find the web search activity 2496cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity); 250f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 25174708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert // Store a consistent set of new values 252875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen synchronized (this) { 253875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mSearchablesMap = newSearchablesMap; 2546d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert mSearchablesList = newSearchablesList; 2556d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList; 256ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mGlobalSearchActivities = newGlobalSearchActivities; 257ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mCurrentGlobalSearchActivity = newGlobalSearchActivity; 2586cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert mWebSearchActivity = newWebSearchActivity; 259875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 260875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 261ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 262ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Returns a sorted list of installed search providers as per 263ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * the following heuristics: 264ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * 265ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * (a) System apps are given priority over non system apps. 266ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * (b) Among system apps and non system apps, the relative ordering 267ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * is defined by their declared priority. 268ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 269ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private List<ResolveInfo> findGlobalSearchActivities() { 270ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Step 1 : Query the package manager for a list 271ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // of activities that can handle the GLOBAL_SEARCH intent. 272ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH); 273ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath List<ResolveInfo> activities = 2745bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 275ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (activities != null && !activities.isEmpty()) { 276ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Step 2: Rank matching activities according to our heuristics. 277ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Collections.sort(activities, GLOBAL_SEARCH_RANKER); 278ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 279ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 280ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return activities; 281ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 282f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 283f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 2846cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Finds the global search activity. 285f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 286ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ComponentName findGlobalSearchActivity(List<ResolveInfo> installed) { 287ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Fetch the global search provider from the system settings, 288ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // and if it's still installed, return it. 289ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath final String searchProviderSetting = getGlobalSearchProviderSetting(); 290ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (!TextUtils.isEmpty(searchProviderSetting)) { 291ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath final ComponentName globalSearchComponent = ComponentName.unflattenFromString( 292ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath searchProviderSetting); 293ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (globalSearchComponent != null && isInstalled(globalSearchComponent)) { 294ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return globalSearchComponent; 295ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 296ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 297ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 298ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return getDefaultGlobalSearchProvider(installed); 299ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 300ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 301ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 302ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Checks whether the global search provider with a given 303ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * component name is installed on the system or not. This deals with 304ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * cases such as the removal of an installed provider. 305ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 306ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private boolean isInstalled(ComponentName globalSearch) { 3076cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH); 308ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath intent.setComponent(globalSearch); 309ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 3105bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani List<ResolveInfo> activities = queryIntentActivities(intent, 3115bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani PackageManager.MATCH_DEFAULT_ONLY); 312ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (activities != null && !activities.isEmpty()) { 313ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return true; 314ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 315ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 316ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return false; 317ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 318ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 319ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private static final Comparator<ResolveInfo> GLOBAL_SEARCH_RANKER = 320ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath new Comparator<ResolveInfo>() { 321ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath @Override 322ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public int compare(ResolveInfo lhs, ResolveInfo rhs) { 323ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (lhs == rhs) { 324ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return 0; 325ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 326ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath boolean lhsSystem = isSystemApp(lhs); 327ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath boolean rhsSystem = isSystemApp(rhs); 328ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 329ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (lhsSystem && !rhsSystem) { 330ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return -1; 331ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } else if (rhsSystem && !lhsSystem) { 332ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return 1; 3336cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert } else { 334ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Either both system engines, or both non system 335ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // engines. 336ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // 337ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Note, this isn't a typo. Higher priority numbers imply 338ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // higher priority, but are "lower" in the sort order. 339ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return rhs.priority - lhs.priority; 3406cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert } 341f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 342ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath }; 343ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 344ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 345ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * @return true iff. the resolve info corresponds to a system application. 346ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 347ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private static final boolean isSystemApp(ResolveInfo res) { 348ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return (res.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 349ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 350ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 351ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 352ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Returns the highest ranked search provider as per the 353ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * ranking defined in {@link #getGlobalSearchActivities()}. 354ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 355ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ComponentName getDefaultGlobalSearchProvider(List<ResolveInfo> providerList) { 356ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (providerList != null && !providerList.isEmpty()) { 357ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath ActivityInfo ai = providerList.get(0).activityInfo; 358ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return new ComponentName(ai.packageName, ai.name); 359ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 360ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 3616cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Log.w(LOG_TAG, "No global search activity found"); 3626cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 363f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 364f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 365ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private String getGlobalSearchProviderSetting() { 366ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return Settings.Secure.getString(mContext.getContentResolver(), 367ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY); 368ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 369ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 3706cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert /** 3716cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Finds the web search activity. 3726cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * 3736cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Only looks in the package of the global search activity. 3746cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert */ 3756cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert private ComponentName findWebSearchActivity(ComponentName globalSearchActivity) { 3766cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert if (globalSearchActivity == null) { 3776cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 3786cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert } 379f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); 3806cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert intent.setPackage(globalSearchActivity.getPackageName()); 3816cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert List<ResolveInfo> activities = 3825bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 383ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 384ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (activities != null && !activities.isEmpty()) { 385ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath ActivityInfo ai = activities.get(0).activityInfo; 3866cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert // TODO: do some sanity checks here? 3876cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return new ComponentName(ai.packageName, ai.name); 388f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 3896cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Log.w(LOG_TAG, "No web search activity found"); 3906cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 391f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 392f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 3935bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { 3945bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani if (mPm == null) { 3955bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani mPm = AppGlobals.getPackageManager(); 3965bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 3975bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani List<ResolveInfo> activities = null; 3985bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani try { 3995bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani activities = 4005bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani mPm.queryIntentActivities(intent, 4015bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani intent.resolveTypeIfNeeded(mContext.getContentResolver()), 4025bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani flags, mUserId); 4035bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } catch (RemoteException re) { 4045bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // Local call 4055bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 4065bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani return activities; 4075bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 4085bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani 409875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 410875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Returns the list of searchable activities. 411875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 412875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public synchronized ArrayList<SearchableInfo> getSearchablesList() { 413875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList); 414875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return result; 415875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 416f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 4176d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert /** 4186d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert * Returns a list of the searchable activities that can be included in global search. 4196d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert */ 4206d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() { 4216d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList); 4226d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert } 423f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 424f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 425ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Returns a list of activities that handle the global search intent. 426ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 427ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() { 428ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return new ArrayList<ResolveInfo>(mGlobalSearchActivities); 429ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 430ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 431ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 4326cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the global search activity. 433f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 4346cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public synchronized ComponentName getGlobalSearchActivity() { 435ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return mCurrentGlobalSearchActivity; 436f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 437f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 438f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 4396cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the web search activity. 440f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 4416cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public synchronized ComponentName getWebSearchActivity() { 4426cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return mWebSearchActivity; 443f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 444875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen} 445