Home | History | Annotate | Download | only in search
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.server.search;
     18 
     19 import com.android.internal.content.PackageMonitor;
     20 
     21 import android.app.ISearchManager;
     22 import android.app.SearchManager;
     23 import android.app.SearchableInfo;
     24 import android.content.BroadcastReceiver;
     25 import android.content.ComponentName;
     26 import android.content.ContentResolver;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.IntentFilter;
     30 import android.content.pm.ResolveInfo;
     31 import android.database.ContentObserver;
     32 import android.os.Process;
     33 import android.provider.Settings;
     34 import android.util.Log;
     35 
     36 import java.util.List;
     37 
     38 /**
     39  * The search manager service handles the search UI, and maintains a registry of searchable
     40  * activities.
     41  */
     42 public class SearchManagerService extends ISearchManager.Stub {
     43 
     44     // general debugging support
     45     private static final String TAG = "SearchManagerService";
     46 
     47     // Context that the service is running in.
     48     private final Context mContext;
     49 
     50     // This field is initialized lazily in getSearchables(), and then never modified.
     51     private Searchables mSearchables;
     52 
     53     private ContentObserver mGlobalSearchObserver;
     54 
     55     /**
     56      * Initializes the Search Manager service in the provided system context.
     57      * Only one instance of this object should be created!
     58      *
     59      * @param context to use for accessing DB, window manager, etc.
     60      */
     61     public SearchManagerService(Context context)  {
     62         mContext = context;
     63         mContext.registerReceiver(new BootCompletedReceiver(),
     64                 new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
     65         mGlobalSearchObserver = new GlobalSearchProviderObserver(
     66                 mContext.getContentResolver());
     67     }
     68 
     69     private synchronized Searchables getSearchables() {
     70         if (mSearchables == null) {
     71             Log.i(TAG, "Building list of searchable activities");
     72             new MyPackageMonitor().register(mContext, null, true);
     73             mSearchables = new Searchables(mContext);
     74             mSearchables.buildSearchableList();
     75         }
     76         return mSearchables;
     77     }
     78 
     79     /**
     80      * Creates the initial searchables list after boot.
     81      */
     82     private final class BootCompletedReceiver extends BroadcastReceiver {
     83         @Override
     84         public void onReceive(Context context, Intent intent) {
     85             new Thread() {
     86                 @Override
     87                 public void run() {
     88                     Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
     89                     mContext.unregisterReceiver(BootCompletedReceiver.this);
     90                     getSearchables();
     91                 }
     92             }.start();
     93         }
     94     }
     95 
     96     /**
     97      * Refreshes the "searchables" list when packages are added/removed.
     98      */
     99     class MyPackageMonitor extends PackageMonitor {
    100 
    101         @Override
    102         public void onSomePackagesChanged() {
    103             updateSearchables();
    104         }
    105 
    106         @Override
    107         public void onPackageModified(String pkg) {
    108             updateSearchables();
    109         }
    110 
    111         private void updateSearchables() {
    112             // Update list of searchable activities
    113             getSearchables().buildSearchableList();
    114             // Inform all listeners that the list of searchables has been updated.
    115             Intent intent = new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
    116             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    117             mContext.sendBroadcast(intent);
    118         }
    119     }
    120 
    121     class GlobalSearchProviderObserver extends ContentObserver {
    122         private final ContentResolver mResolver;
    123 
    124         public GlobalSearchProviderObserver(ContentResolver resolver) {
    125             super(null);
    126             mResolver = resolver;
    127             mResolver.registerContentObserver(
    128                     Settings.Secure.getUriFor(Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY),
    129                     false /* notifyDescendants */,
    130                     this);
    131         }
    132 
    133         @Override
    134         public void onChange(boolean selfChange) {
    135             getSearchables().buildSearchableList();
    136             Intent intent = new Intent(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
    137             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    138             mContext.sendBroadcast(intent);
    139         }
    140 
    141     }
    142 
    143     //
    144     // Searchable activities API
    145     //
    146 
    147     /**
    148      * Returns the SearchableInfo for a given activity.
    149      *
    150      * @param launchActivity The activity from which we're launching this search.
    151      * @return Returns a SearchableInfo record describing the parameters of the search,
    152      * or null if no searchable metadata was available.
    153      */
    154     public SearchableInfo getSearchableInfo(final ComponentName launchActivity) {
    155         if (launchActivity == null) {
    156             Log.e(TAG, "getSearchableInfo(), activity == null");
    157             return null;
    158         }
    159         return getSearchables().getSearchableInfo(launchActivity);
    160     }
    161 
    162     /**
    163      * Returns a list of the searchable activities that can be included in global search.
    164      */
    165     public List<SearchableInfo> getSearchablesInGlobalSearch() {
    166         return getSearchables().getSearchablesInGlobalSearchList();
    167     }
    168 
    169     public List<ResolveInfo> getGlobalSearchActivities() {
    170         return getSearchables().getGlobalSearchActivities();
    171     }
    172 
    173     /**
    174      * Gets the name of the global search activity.
    175      */
    176     public ComponentName getGlobalSearchActivity() {
    177         return getSearchables().getGlobalSearchActivity();
    178     }
    179 
    180     /**
    181      * Gets the name of the web search activity.
    182      */
    183     public ComponentName getWebSearchActivity() {
    184         return getSearchables().getWebSearchActivity();
    185     }
    186 
    187 }
    188