SearchManagerService.java revision 13bc602b2118af550c7ed99c4582fb7db7622002
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.server.search; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringertimport com.android.internal.content.PackageMonitor; 20ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ISearchManager; 228d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.app.SearchManager; 232126aac7f992b57fc52141a8bd09fa7a45ac2509Bjorn Bringertimport android.app.SearchableInfo; 242c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringertimport android.content.BroadcastReceiver; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName; 26ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.ContentResolver; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 292c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringertimport android.content.IntentFilter; 30ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.content.pm.ResolveInfo; 31ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.database.ContentObserver; 322c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringertimport android.os.Process; 33ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamathimport android.provider.Settings; 348d17f3f24bbda9a9cd7ea08c5925508dc2c011beBjorn Bringertimport android.util.Log; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 366d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringertimport java.util.List; 376d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 39444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * The search manager service handles the search UI, and maintains a registry of searchable 40444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * activities. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 42444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringertpublic class SearchManagerService extends ISearchManager.Stub { 43444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 44444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // general debugging support 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "SearchManagerService"; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // Context that the service is running in. 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Context mContext; 49f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 50ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert // This field is initialized lazily in getSearchables(), and then never modified. 519bc75cb9c23e5df528a28acc1fbbb4b5be51c33dBjorn Bringert private Searchables mSearchables; 523ed6a3342b89651e8359956cefcc0076b6a4a30aKarl Rosaen 53ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private ContentObserver mGlobalSearchObserver; 54ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 56875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * Initializes the Search Manager service in the provided system context. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Only one instance of this object should be created! 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context to use for accessing DB, window manager, etc. 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 61f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath public SearchManagerService(Context context) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 632c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert mContext.registerReceiver(new BootCompletedReceiver(), 642c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); 65ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mGlobalSearchObserver = new GlobalSearchProviderObserver( 66ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mContext.getContentResolver()); 67444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert } 68444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert 699bc75cb9c23e5df528a28acc1fbbb4b5be51c33dBjorn Bringert private synchronized Searchables getSearchables() { 70ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert if (mSearchables == null) { 712c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert Log.i(TAG, "Building list of searchable activities"); 722c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert new MyPackageMonitor().register(mContext, true); 73ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert mSearchables = new Searchables(mContext); 74ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert mSearchables.buildSearchableList(); 75ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert } 769bc75cb9c23e5df528a28acc1fbbb4b5be51c33dBjorn Bringert return mSearchables; 779bc75cb9c23e5df528a28acc1fbbb4b5be51c33dBjorn Bringert } 783ed6a3342b89651e8359956cefcc0076b6a4a30aKarl Rosaen 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 802c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert * Creates the initial searchables list after boot. 812c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert */ 822c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert private final class BootCompletedReceiver extends BroadcastReceiver { 832c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert @Override 842c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert public void onReceive(Context context, Intent intent) { 852c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert new Thread() { 862c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert @Override 872c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert public void run() { 882c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 892c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert mContext.unregisterReceiver(BootCompletedReceiver.this); 902c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert getSearchables(); 912c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert } 922c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert }.start(); 932c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert } 942c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert } 952c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert 962c7b197a4ab1aff671a6fa2e6db540d391f553e6Bjorn Bringert /** 97444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * Refreshes the "searchables" list when packages are added/removed. 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 99ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert class MyPackageMonitor extends PackageMonitor { 10013bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 102ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert public void onSomePackagesChanged() { 10313bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani updateSearchables(); 10413bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani } 10513bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani 10613bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani @Override 10713bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani public void onPackageModified(String pkg) { 10813bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani updateSearchables(); 10913bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani } 11013bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani 11113bc602b2118af550c7ed99c4582fb7db7622002Amith Yamasani private void updateSearchables() { 112ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert // Update list of searchable activities 113ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert getSearchables().buildSearchableList(); 114ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert // Inform all listeners that the list of searchables has been updated. 115ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); 116ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 117ab5d96c5daf4bcc9b7a0cde44357454a11a8e48aBjorn Bringert mContext.sendBroadcast(intent); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 121ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath class GlobalSearchProviderObserver extends ContentObserver { 122ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath private final ContentResolver mResolver; 123ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 124ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public GlobalSearchProviderObserver(ContentResolver resolver) { 125ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath super(null); 126ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mResolver = resolver; 127ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mResolver.registerContentObserver( 128ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY), 129ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath false /* notifyDescendants */, 130ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath this); 131ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 132ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 133ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath @Override 134ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public void onChange(boolean selfChange) { 135ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath getSearchables().buildSearchableList(); 136ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); 137ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 138ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath mContext.sendBroadcast(intent); 139ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 140ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 141ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 142ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 143444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // 144444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // Searchable activities API 145444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert // 146a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert 147a48a5af931f2fb43c948416180b85dfe9ecdc9a1Bjorn Bringert /** 148444c727e0eecf83e9d0b9c4e7af5cbf5fc4135f8Bjorn Bringert * Returns the SearchableInfo for a given activity. 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param launchActivity The activity from which we're launching this search. 151875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * @return Returns a SearchableInfo record describing the parameters of the search, 152875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen * or null if no searchable metadata was available. 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1546cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public SearchableInfo getSearchableInfo(final ComponentName launchActivity) { 1556cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert if (launchActivity == null) { 1566cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert Log.e(TAG, "getSearchableInfo(), activity == null"); 1576cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return null; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1596cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return getSearchables().getSearchableInfo(launchActivity); 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 161f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 1626d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert /** 1636d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert * Returns a list of the searchable activities that can be included in global search. 1646d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert */ 1656d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert public List<SearchableInfo> getSearchablesInGlobalSearch() { 1669bc75cb9c23e5df528a28acc1fbbb4b5be51c33dBjorn Bringert return getSearchables().getSearchablesInGlobalSearchList(); 1676d72e029cb6e5a9cf26aa3314c3dca83614fc91bBjorn Bringert } 168875d50a4b9294b2be33cff6493cae7acd1d07ea7Karl Rosaen 169ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath public List<ResolveInfo> getGlobalSearchActivities() { 170ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath return getSearchables().getGlobalSearchActivities(); 171ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath } 172ee69ff4eaee9342843d5f25338288865dda2d36aNarayan Kamath 173f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 1746cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the global search activity. 175f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 1766cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public ComponentName getGlobalSearchActivity() { 1776cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return getSearchables().getGlobalSearchActivity(); 178f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 179f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 180f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath /** 1816cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert * Gets the name of the web search activity. 182f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath */ 1836cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert public ComponentName getWebSearchActivity() { 1846cf7a325e6e9e70d9858e21fbb438341332ed254Bjorn Bringert return getSearchables().getWebSearchActivity(); 185f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath } 186f9acde27486bcc6eea1092073f7b47c31749efd6Satish Sampath 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 188