149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert/*
249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * Copyright (C) 2010 The Android Open Source Project
349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert *
449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * you may not use this file except in compliance with the License.
649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * You may obtain a copy of the License at
749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert *
849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert *
1049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
1149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
1249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * See the License for the specific language governing permissions and
1449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * limitations under the License.
1549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert */
1649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
1749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertpackage com.android.quicksearchbox;
1849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
19516781305d7427e79928c95c6ea2b7689a4bf6ceMathew Inwoodimport com.android.quicksearchbox.util.NamedTaskExecutor;
20e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwoodimport com.android.quicksearchbox.util.NowOrLater;
215229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood
2249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.app.SearchManager;
2349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.content.ComponentName;
2449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.content.Context;
2549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.content.Intent;
2649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.graphics.drawable.Drawable;
2749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.net.Uri;
2849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.os.Bundle;
29e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwoodimport android.os.Handler;
3049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertimport android.util.Log;
3149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
3249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert/**
3349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert * Abstract suggestion source implementation.
3449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert */
3549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringertpublic abstract class AbstractSource implements Source {
3649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
3749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    private static final String TAG = "QSB.AbstractSource";
3849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
3949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    private final Context mContext;
40e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood    private final Handler mUiThread;
4149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
4249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    private IconLoader mIconLoader;
4349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
44516781305d7427e79928c95c6ea2b7689a4bf6ceMathew Inwood    private final NamedTaskExecutor mIconLoaderExecutor;
455229b06f00d20aac76cd8519b37f2a579d61c54fMathew Inwood
46516781305d7427e79928c95c6ea2b7689a4bf6ceMathew Inwood    public AbstractSource(Context context, Handler uiThread, NamedTaskExecutor iconLoader) {
4749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        mContext = context;
48e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood        mUiThread = uiThread;
49516781305d7427e79928c95c6ea2b7689a4bf6ceMathew Inwood        mIconLoaderExecutor = iconLoader;
5049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
5149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
5249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    protected Context getContext() {
5349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return mContext;
5449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
5549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
5649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    protected IconLoader getIconLoader() {
5749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        if (mIconLoader == null) {
5849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            String iconPackage = getIconPackage();
59e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood            mIconLoader = new CachingIconLoader(
60516781305d7427e79928c95c6ea2b7689a4bf6ceMathew Inwood                    new PackageIconLoader(mContext, iconPackage, mUiThread, mIconLoaderExecutor));
6149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        }
6249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return mIconLoader;
6349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
6449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
6549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    protected abstract String getIconPackage();
6649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
6725cbd7d054b92df1fe857d155ccc12f8191c12cfMathew Inwood    public boolean isVersionCodeCompatible(int version) {
6825cbd7d054b92df1fe857d155ccc12f8191c12cfMathew Inwood        return getVersionCode() == version;
6925cbd7d054b92df1fe857d155ccc12f8191c12cfMathew Inwood    }
7025cbd7d054b92df1fe857d155ccc12f8191c12cfMathew Inwood
71e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood    public NowOrLater<Drawable> getIcon(String drawableId) {
7249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return getIconLoader().getIcon(drawableId);
7349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
7449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
7549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    public Uri getIconUri(String drawableId) {
7649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return getIconLoader().getIconUri(drawableId);
7749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
7849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
7949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    public Intent createSearchIntent(String query, Bundle appData) {
8049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return createSourceSearchIntent(getIntentComponent(), query, appData);
8149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
8249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
8349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    public static Intent createSourceSearchIntent(ComponentName activity, String query,
8449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            Bundle appData) {
8549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        if (activity == null) {
8649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            Log.w(TAG, "Tried to create search intent with no target activity");
8749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            return null;
8849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        }
8949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        Intent intent = new Intent(Intent.ACTION_SEARCH);
9049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        intent.setComponent(activity);
9149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        // We need CLEAR_TOP to avoid reusing an old task that has other activities
9349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        // on top of the one we want.
9449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
9549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        intent.putExtra(SearchManager.USER_QUERY, query);
9649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        intent.putExtra(SearchManager.QUERY, query);
9749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        if (appData != null) {
9849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert            intent.putExtra(SearchManager.APP_DATA, appData);
9949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        }
10049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return intent;
10149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
10249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
10349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    protected Intent createVoiceWebSearchIntent(Bundle appData) {
10449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return QsbApplication.get(mContext).getVoiceSearch()
10549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert                .createVoiceWebSearchIntent(appData);
10649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
10749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
108848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    public Source getRoot() {
109848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        return this;
110848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani    }
111848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani
11249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    @Override
11349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    public boolean equals(Object o) {
114848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani        if (o != null && o instanceof Source) {
115848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani            Source s = ((Source) o).getRoot();
116848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani            if (s.getClass().equals(this.getClass())) {
117848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani                return s.getName().equals(getName());
118848fa7a19abedc372452073abaf52780c7b6d78dAmith Yamasani            }
11949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        }
12049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return false;
12149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
12249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
12349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    @Override
12449fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    public int hashCode() {
12549fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return getName().hashCode();
12649fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
12749fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
12849fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    @Override
12949fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    public String toString() {
13049fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert        return "Source{name=" + getName() + "}";
13149fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert    }
13249fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert
13349fd8e0994577badc6194c2c3b5f771f2b793fe4Bjorn Bringert}
134