blob: fe155536ba549e9d7bf8aeaf795187cb268fbb1a [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.server.search;
import android.app.ISearchManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.util.Config;
/**
* This is a simplified version of the Search Manager service. It no longer handles
* presentation (UI). Its function is to maintain the map & list of "searchable"
* items, which provides a mapping from individual activities (where a user might have
* invoked search) to specific searchable activities (where the search will be dispatched).
*/
public class SearchManagerService extends ISearchManager.Stub
{
// general debugging support
private static final String TAG = "SearchManagerService";
private static final boolean DEBUG = false;
private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
// configuration choices
private static final boolean IMMEDIATE_SEARCHABLES_UPDATE = true;
// class maintenance and general shared data
private final Context mContext;
private final Handler mHandler;
private boolean mSearchablesDirty;
/**
* Initialize the Search Manager service in the provided system context.
* Only one instance of this object should be created!
*
* @param context to use for accessing DB, window manager, etc.
*/
public SearchManagerService(Context context) {
mContext = context;
mHandler = new Handler();
// Setup the infrastructure for updating and maintaining the list
// of searchable activities.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
mSearchablesDirty = true;
// After startup settles down, preload the searchables list,
// which will reduce the delay when the search UI is invoked.
if (IMMEDIATE_SEARCHABLES_UPDATE) {
mHandler.post(mRunUpdateSearchable);
}
}
/**
* Listens for intent broadcasts.
*
* The primary purpose here is to refresh the "searchables" list
* if packages are added/removed.
*/
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// First, test for intents that matter at any time
if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
action.equals(Intent.ACTION_PACKAGE_CHANGED)) {
mSearchablesDirty = true;
if (IMMEDIATE_SEARCHABLES_UPDATE) {
mHandler.post(mRunUpdateSearchable);
}
return;
}
}
};
/**
* This runnable (for the main handler / UI thread) will update the searchables list.
*/
private Runnable mRunUpdateSearchable = new Runnable() {
public void run() {
if (mSearchablesDirty) {
updateSearchables();
}
}
};
/**
* Update the list of searchables, either at startup or in response to
* a package add/remove broadcast message.
*/
private void updateSearchables() {
SearchableInfo.buildSearchableList(mContext);
mSearchablesDirty = false;
// TODO This is a hack. This shouldn't be hardcoded here, it's probably
// a policy.
// ComponentName defaultSearch = new ComponentName(
// "com.android.contacts",
// "com.android.contacts.ContactsListActivity" );
ComponentName defaultSearch = new ComponentName(
"com.android.googlesearch",
"com.android.googlesearch.GoogleSearch" );
SearchableInfo.setDefaultSearchable(mContext, defaultSearch);
}
/**
* Return the searchableinfo for a given activity
*
* @param launchActivity The activity from which we're launching this search.
* @return Returns a SearchableInfo record describing the parameters of the search,
* or null if no searchable metadata was available.
* @param globalSearch If false, this will only launch the search that has been specifically
* defined by the application (which is usually defined as a local search). If no default
* search is defined in the current application or activity, no search will be launched.
* If true, this will always launch a platform-global (e.g. web-based) search instead.
*/
public SearchableInfo getSearchableInfo(ComponentName launchActivity, boolean globalSearch) {
// final check. however we should try to avoid this, because
// it slows down the entry into the UI.
if (mSearchablesDirty) {
updateSearchables();
}
SearchableInfo si = null;
if (globalSearch) {
si = SearchableInfo.getDefaultSearchable();
} else {
si = SearchableInfo.getSearchableInfo(mContext, launchActivity);
}
return si;
}
}