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 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.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; 30f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasaniimport android.os.Binder; 31875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport android.os.Bundle; 325bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasaniimport android.os.RemoteException; 33ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.provider.Settings; 34ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.text.TextUtils; 35cbd8a246f86704fb348247245904a9f114f11280Satish Sampathimport android.util.Log; 36875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 3764442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport java.io.FileDescriptor; 3864442c11555d828a41af0b8a58ab933357889061Amith Yamasaniimport java.io.PrintWriter; 39875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport java.util.ArrayList; 40ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport java.util.Collections; 41ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport java.util.Comparator; 42875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport java.util.HashMap; 43875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenimport java.util.List; 44875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 45875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen/** 46f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * This class maintains the information about all searchable activities. 475bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani * This is a hidden class. 48875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 49875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaenpublic class Searchables { 50875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 51cbd8a246f86704fb348247245904a9f114f11280Satish Sampath private static final String LOG_TAG = "Searchables"; 52cbd8a246f86704fb348247245904a9f114f11280Satish Sampath 53875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // static strings used for XML lookups, etc. 54f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // TODO how should these be documented for the developer, in a more structured way than 55875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // the current long wordy javadoc in SearchManager.java ? 56875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable"; 57875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*"; 58f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 59875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private Context mContext; 60f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 61875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null; 62875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen private ArrayList<SearchableInfo> mSearchablesList = null; 636d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null; 64ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Contains all installed activities that handle the global search 65ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // intent. 66ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private List<ResolveInfo> mGlobalSearchActivities; 67ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ComponentName mCurrentGlobalSearchActivity = null; 686cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert private ComponentName mWebSearchActivity = null; 69f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 7041282a35568b51270440450c46bb31aa00e52caaSatish Sampath public static String GOOGLE_SEARCH_COMPONENT_NAME = 7141282a35568b51270440450c46bb31aa00e52caaSatish Sampath "com.android.googlesearch/.GoogleSearch"; 7241282a35568b51270440450c46bb31aa00e52caaSatish Sampath public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME = 7341282a35568b51270440450c46bb31aa00e52caaSatish Sampath "com.google.android.providers.enhancedgooglesearch/.Launcher"; 7441282a35568b51270440450c46bb31aa00e52caaSatish Sampath 755bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // Cache the package manager instance 76f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani final private IPackageManager mPm; 775bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // User for which this Searchables caches information 785bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani private int mUserId; 795bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani 80875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 81f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 82875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @param context Context to use for looking up activities etc. 83875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 845bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani public Searchables (Context context, int userId) { 85875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen mContext = context; 865bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani mUserId = userId; 87f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani mPm = AppGlobals.getPackageManager(); 88875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 89f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 90875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 91875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Look up, or construct, based on the activity. 92f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 93f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * The activities fall into three cases, based on meta-data found in 94875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * the manifest entry: 95875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <ol> 96875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <li>The activity itself implements search. This is indicated by the 97875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * presence of a "android.app.searchable" meta-data attribute. 98875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * The value is a reference to an XML file containing search information.</li> 99875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <li>A related activity implements search. This is indicated by the 100875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * presence of a "android.app.default_searchable" meta-data attribute. 101875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * The value is a string naming the activity implementing search. In this 102875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * case the factory will "redirect" and return the searchable data.</li> 103875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * <li>No searchability data is provided. We return null here and other 104875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * code will insert the "default" (e.g. contacts) search. 105f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 106875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: cache the result in the map, and check the map first. 107875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: it might make sense to implement the searchable reference as 108875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * an application meta-data entry. This way we don't have to pepper each 109875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * and every activity. 110875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: can we skip the constructor step if it's a non-searchable? 111f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * TODO: does it make sense to plug the default into a slot here for 112875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * automatic return? Probably not, but it's one way to do it. 113875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * 114f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * @param activity The name of the current activity, or null if the 115875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * activity does not define any explicit searchable metadata. 116875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 117875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public SearchableInfo getSearchableInfo(ComponentName activity) { 118875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Step 1. Is the result already hashed? (case 1) 119875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen SearchableInfo result; 120875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen synchronized (this) { 121875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen result = mSearchablesMap.get(activity); 122875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (result != null) return result; 123875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 124f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 125875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Step 2. See if the current activity references a searchable. 126875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Note: Conceptually, this could be a while(true) loop, but there's 127f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // no point in implementing reference chaining here and risking a loop. 128875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // References must point directly to searchable activities. 129f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 130875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ActivityInfo ai = null; 131875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen try { 132f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani ai = mPm.getActivityInfo(activity, PackageManager.GET_META_DATA, mUserId); 133f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } catch (RemoteException re) { 134f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani Log.e(LOG_TAG, "Error getting activity info " + re); 135f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani return null; 136f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } 137f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani String refActivityName = null; 138f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 139f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani // First look for activity-specific reference 140f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani Bundle md = ai.metaData; 141f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani if (md != null) { 142f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); 143f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } 144f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani // If not found, try for app-wide reference 145f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani if (refActivityName == null) { 146f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani md = ai.applicationInfo.metaData; 147875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen if (md != null) { 148875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE); 149875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 150f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } 151f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 152f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani // Irrespective of source, if a reference was found, follow it. 153f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani if (refActivityName != null) 154f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani { 155f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani // This value is deprecated, return null 156f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) { 157f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani return null; 158f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } 159f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani String pkg = activity.getPackageName(); 160f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani ComponentName referredActivity; 161f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani if (refActivityName.charAt(0) == '.') { 162f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani referredActivity = new ComponentName(pkg, pkg + refActivityName); 163f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } else { 164f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani referredActivity = new ComponentName(pkg, refActivityName); 165f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani } 166875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 167f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani // Now try the referred activity, and if found, cache 168f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani // it against the original name so we can skip the check 169f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani synchronized (this) { 170f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani result = mSearchablesMap.get(referredActivity); 171f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani if (result != null) { 172f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani mSearchablesMap.put(activity, result); 173f203aeef993b0f4ce65c9630d06bbd50a504e89fAmith Yamasani return result; 174875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 175875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 176875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 177f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 178875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen // Step 3. None found. Return null. 179875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return null; 180f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 181875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 182f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 183875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 184f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * Builds an entire list (suitable for display) of 185f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * activities that are searchable, by iterating the entire set of 186f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * ACTION_SEARCH & ACTION_WEB_SEARCH intents. 187f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 188875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Also clears the hash of all activities -> searches which will 189875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * refill as the user clicks "search". 190f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 191875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * This should only be done at startup and again if we know that the 192875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * list has changed. 193f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 194875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: every activity that provides a ACTION_SEARCH intent should 195875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * also provide searchability meta-data. There are a bunch of checks here 196875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * that, if data is not found, silently skip to the next activity. This 197875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * won't help a developer trying to figure out why their activity isn't 198875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * showing up in the list, but an exception here is too rough. I would 199875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * like to find a better notification mechanism. 200f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath * 201875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * TODO: sort the list somehow? UI choice. 202875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 203875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public void buildSearchableList() { 20474708bbdf8d6f172b08343bdc578a20aa4b39148Bjorn Bringert // These will become the new values at the end of the method 205f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath HashMap<ComponentName, SearchableInfo> newSearchablesMap 206875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen = new HashMap<ComponentName, SearchableInfo>(); 207875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ArrayList<SearchableInfo> newSearchablesList 208875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen = new ArrayList<SearchableInfo>(); 2096d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert ArrayList<SearchableInfo> newSearchablesInGlobalSearchList 2106d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert = new ArrayList<SearchableInfo>(); 211875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 212f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers. 213f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath List<ResolveInfo> searchList; 214875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen final Intent intent = new Intent(Intent.ACTION_SEARCH); 21564442c11555d828a41af0b8a58ab933357889061Amith Yamasani 21664442c11555d828a41af0b8a58ab933357889061Amith Yamasani long ident = Binder.clearCallingIdentity(); 21764442c11555d828a41af0b8a58ab933357889061Amith Yamasani try { 21864442c11555d828a41af0b8a58ab933357889061Amith Yamasani searchList = queryIntentActivities(intent, PackageManager.GET_META_DATA); 21964442c11555d828a41af0b8a58ab933357889061Amith Yamasani 22064442c11555d828a41af0b8a58ab933357889061Amith Yamasani List<ResolveInfo> webSearchInfoList; 22164442c11555d828a41af0b8a58ab933357889061Amith Yamasani final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH); 22264442c11555d828a41af0b8a58ab933357889061Amith Yamasani webSearchInfoList = queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA); 22364442c11555d828a41af0b8a58ab933357889061Amith Yamasani 22464442c11555d828a41af0b8a58ab933357889061Amith Yamasani // analyze each one, generate a Searchables record, and record 22564442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (searchList != null || webSearchInfoList != null) { 22664442c11555d828a41af0b8a58ab933357889061Amith Yamasani int search_count = (searchList == null ? 0 : searchList.size()); 22764442c11555d828a41af0b8a58ab933357889061Amith Yamasani int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size()); 22864442c11555d828a41af0b8a58ab933357889061Amith Yamasani int count = search_count + web_search_count; 22964442c11555d828a41af0b8a58ab933357889061Amith Yamasani for (int ii = 0; ii < count; ii++) { 23064442c11555d828a41af0b8a58ab933357889061Amith Yamasani // for each component, try to find metadata 23164442c11555d828a41af0b8a58ab933357889061Amith Yamasani ResolveInfo info = (ii < search_count) 23264442c11555d828a41af0b8a58ab933357889061Amith Yamasani ? searchList.get(ii) 23364442c11555d828a41af0b8a58ab933357889061Amith Yamasani : webSearchInfoList.get(ii - search_count); 23464442c11555d828a41af0b8a58ab933357889061Amith Yamasani ActivityInfo ai = info.activityInfo; 23564442c11555d828a41af0b8a58ab933357889061Amith Yamasani // Check first to avoid duplicate entries. 23664442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) { 23764442c11555d828a41af0b8a58ab933357889061Amith Yamasani SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai, 23864442c11555d828a41af0b8a58ab933357889061Amith Yamasani mUserId); 23964442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (searchable != null) { 24064442c11555d828a41af0b8a58ab933357889061Amith Yamasani newSearchablesList.add(searchable); 24164442c11555d828a41af0b8a58ab933357889061Amith Yamasani newSearchablesMap.put(searchable.getSearchActivity(), searchable); 24264442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (searchable.shouldIncludeInGlobalSearch()) { 24364442c11555d828a41af0b8a58ab933357889061Amith Yamasani newSearchablesInGlobalSearchList.add(searchable); 24464442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 245590f63433ce786722d263c7e913a88d3101e5cbcKarl Rosaen } 2466d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert } 247875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 248875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 249f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 25064442c11555d828a41af0b8a58ab933357889061Amith Yamasani List<ResolveInfo> newGlobalSearchActivities = findGlobalSearchActivities(); 251ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 25264442c11555d828a41af0b8a58ab933357889061Amith Yamasani // Find the global search activity 25364442c11555d828a41af0b8a58ab933357889061Amith Yamasani ComponentName newGlobalSearchActivity = findGlobalSearchActivity( 25464442c11555d828a41af0b8a58ab933357889061Amith Yamasani newGlobalSearchActivities); 255cbd8a246f86704fb348247245904a9f114f11280Satish Sampath 25664442c11555d828a41af0b8a58ab933357889061Amith Yamasani // Find the web search activity 25764442c11555d828a41af0b8a58ab933357889061Amith Yamasani ComponentName newWebSearchActivity = findWebSearchActivity(newGlobalSearchActivity); 258f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 25964442c11555d828a41af0b8a58ab933357889061Amith Yamasani // Store a consistent set of new values 26064442c11555d828a41af0b8a58ab933357889061Amith Yamasani synchronized (this) { 26164442c11555d828a41af0b8a58ab933357889061Amith Yamasani mSearchablesMap = newSearchablesMap; 26264442c11555d828a41af0b8a58ab933357889061Amith Yamasani mSearchablesList = newSearchablesList; 26364442c11555d828a41af0b8a58ab933357889061Amith Yamasani mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList; 26464442c11555d828a41af0b8a58ab933357889061Amith Yamasani mGlobalSearchActivities = newGlobalSearchActivities; 26564442c11555d828a41af0b8a58ab933357889061Amith Yamasani mCurrentGlobalSearchActivity = newGlobalSearchActivity; 26664442c11555d828a41af0b8a58ab933357889061Amith Yamasani mWebSearchActivity = newWebSearchActivity; 26764442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 26864442c11555d828a41af0b8a58ab933357889061Amith Yamasani } finally { 26964442c11555d828a41af0b8a58ab933357889061Amith Yamasani Binder.restoreCallingIdentity(ident); 270875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 271875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 27264442c11555d828a41af0b8a58ab933357889061Amith Yamasani 273ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 274ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Returns a sorted list of installed search providers as per 275ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * the following heuristics: 276ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * 277ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * (a) System apps are given priority over non system apps. 278ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * (b) Among system apps and non system apps, the relative ordering 279ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * is defined by their declared priority. 280ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 281ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private List<ResolveInfo> findGlobalSearchActivities() { 282ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Step 1 : Query the package manager for a list 283ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // of activities that can handle the GLOBAL_SEARCH intent. 284ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH); 285ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath List<ResolveInfo> activities = 2865bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 287ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (activities != null && !activities.isEmpty()) { 288ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Step 2: Rank matching activities according to our heuristics. 289ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Collections.sort(activities, GLOBAL_SEARCH_RANKER); 290ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 291ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 292ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return activities; 293ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 294f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 295f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 2966cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Finds the global search activity. 297f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 298ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ComponentName findGlobalSearchActivity(List<ResolveInfo> installed) { 299ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Fetch the global search provider from the system settings, 300ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // and if it's still installed, return it. 301ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath final String searchProviderSetting = getGlobalSearchProviderSetting(); 302ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (!TextUtils.isEmpty(searchProviderSetting)) { 303ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath final ComponentName globalSearchComponent = ComponentName.unflattenFromString( 304ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath searchProviderSetting); 305ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (globalSearchComponent != null && isInstalled(globalSearchComponent)) { 306ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return globalSearchComponent; 307ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 308ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 309ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 310ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return getDefaultGlobalSearchProvider(installed); 311ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 312ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 313ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 314ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Checks whether the global search provider with a given 315ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * component name is installed on the system or not. This deals with 316ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * cases such as the removal of an installed provider. 317ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 318ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private boolean isInstalled(ComponentName globalSearch) { 3196cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH); 320ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath intent.setComponent(globalSearch); 321ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 3225bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani List<ResolveInfo> activities = queryIntentActivities(intent, 3235bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani PackageManager.MATCH_DEFAULT_ONLY); 324ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (activities != null && !activities.isEmpty()) { 325ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return true; 326ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 327ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 328ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return false; 329ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 330ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 331ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private static final Comparator<ResolveInfo> GLOBAL_SEARCH_RANKER = 332ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath new Comparator<ResolveInfo>() { 333ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath @Override 334ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public int compare(ResolveInfo lhs, ResolveInfo rhs) { 335ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (lhs == rhs) { 336ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return 0; 337ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 338ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath boolean lhsSystem = isSystemApp(lhs); 339ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath boolean rhsSystem = isSystemApp(rhs); 340ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 341ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (lhsSystem && !rhsSystem) { 342ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return -1; 343ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } else if (rhsSystem && !lhsSystem) { 344ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return 1; 3456cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert } else { 346ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Either both system engines, or both non system 347ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // engines. 348ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // 349ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // Note, this isn't a typo. Higher priority numbers imply 350ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath // higher priority, but are "lower" in the sort order. 351ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return rhs.priority - lhs.priority; 3526cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert } 353f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 354ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath }; 355ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 356ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 357ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * @return true iff. the resolve info corresponds to a system application. 358ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 359ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private static final boolean isSystemApp(ResolveInfo res) { 360ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return (res.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 361ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 362ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 363ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 364ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Returns the highest ranked search provider as per the 365ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * ranking defined in {@link #getGlobalSearchActivities()}. 366ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 367ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ComponentName getDefaultGlobalSearchProvider(List<ResolveInfo> providerList) { 368ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (providerList != null && !providerList.isEmpty()) { 369ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath ActivityInfo ai = providerList.get(0).activityInfo; 370ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return new ComponentName(ai.packageName, ai.name); 371ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 372ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 3736cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Log.w(LOG_TAG, "No global search activity found"); 3746cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 375f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 376f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 377ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private String getGlobalSearchProviderSetting() { 378ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return Settings.Secure.getString(mContext.getContentResolver(), 379ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY); 380ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 381ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 3826cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert /** 3836cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Finds the web search activity. 3846cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * 3856cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Only looks in the package of the global search activity. 3866cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert */ 3876cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert private ComponentName findWebSearchActivity(ComponentName globalSearchActivity) { 3886cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert if (globalSearchActivity == null) { 3896cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 3906cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert } 391f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath Intent intent = new Intent(Intent.ACTION_WEB_SEARCH); 3926cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert intent.setPackage(globalSearchActivity.getPackageName()); 3936cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert List<ResolveInfo> activities = 3945bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); 395ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 396ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath if (activities != null && !activities.isEmpty()) { 397ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath ActivityInfo ai = activities.get(0).activityInfo; 3986cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert // TODO: do some sanity checks here? 3996cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return new ComponentName(ai.packageName, ai.name); 400f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 4016cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Log.w(LOG_TAG, "No web search activity found"); 4026cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 403f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 404f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 4055bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani private List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { 4065bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani List<ResolveInfo> activities = null; 4075bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani try { 4085bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani activities = 4095bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani mPm.queryIntentActivities(intent, 4105bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani intent.resolveTypeIfNeeded(mContext.getContentResolver()), 4115bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani flags, mUserId); 4125bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } catch (RemoteException re) { 4135bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani // Local call 4145bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 4155bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani return activities; 4165bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani } 4175bb87cd9b81506b0c25d3f9184e406762a9e9d9cAmith Yamasani 418875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen /** 419875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Returns the list of searchable activities. 420875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen */ 421875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen public synchronized ArrayList<SearchableInfo> getSearchablesList() { 422875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList); 423875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen return result; 424875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen } 425f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 4266d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert /** 4276d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert * Returns a list of the searchable activities that can be included in global search. 4286d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert */ 4296d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() { 4306d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList); 4316d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert } 432f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 433f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 434ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath * Returns a list of activities that handle the global search intent. 435ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath */ 436ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public synchronized ArrayList<ResolveInfo> getGlobalSearchActivities() { 437ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return new ArrayList<ResolveInfo>(mGlobalSearchActivities); 438ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 439ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 440ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath /** 4416cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the global search activity. 442f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 4436cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public synchronized ComponentName getGlobalSearchActivity() { 444ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return mCurrentGlobalSearchActivity; 445f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 446f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 447f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 4486cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the web search activity. 449f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 4506cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public synchronized ComponentName getWebSearchActivity() { 4516cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return mWebSearchActivity; 452f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 45364442c11555d828a41af0b8a58ab933357889061Amith Yamasani 45464442c11555d828a41af0b8a58ab933357889061Amith Yamasani void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 45564442c11555d828a41af0b8a58ab933357889061Amith Yamasani pw.println("Searchable authorities:"); 45664442c11555d828a41af0b8a58ab933357889061Amith Yamasani synchronized (this) { 45764442c11555d828a41af0b8a58ab933357889061Amith Yamasani if (mSearchablesList != null) { 45864442c11555d828a41af0b8a58ab933357889061Amith Yamasani for (SearchableInfo info: mSearchablesList) { 45964442c11555d828a41af0b8a58ab933357889061Amith Yamasani pw.print(" "); pw.println(info.getSuggestAuthority()); 46064442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 46164442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 46264442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 46364442c11555d828a41af0b8a58ab933357889061Amith Yamasani } 464875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen} 465