QsbApplication.java revision f95ce100dcbc77794b79b0187c566bb58b5978d3
13e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert/*
23e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project
33e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *
43e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
53e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * you may not use this file except in compliance with the License.
63e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * You may obtain a copy of the License at
73e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *
83e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
93e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert *
103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * See the License for the specific language governing permissions and
143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert * limitations under the License.
153e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert */
163e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpackage com.android.quicksearchbox;
183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
19c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringertimport com.android.quicksearchbox.ui.CorpusViewFactory;
20c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringertimport com.android.quicksearchbox.ui.CorpusViewInflater;
21816804b67619af133860a1e28e92f58bc642260dBjorn Bringertimport com.android.quicksearchbox.ui.DelayingSuggestionsAdapter;
22dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringertimport com.android.quicksearchbox.ui.EmptySuggestionsFooter;
23185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionViewFactory;
24185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionViewInflater;
25816804b67619af133860a1e28e92f58bc642260dBjorn Bringertimport com.android.quicksearchbox.ui.SuggestionsAdapter;
26883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringertimport com.android.quicksearchbox.ui.SuggestionsFooter;
2772f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringertimport com.android.quicksearchbox.util.Factory;
28a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport com.android.quicksearchbox.util.NamedTaskExecutor;
29a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport com.android.quicksearchbox.util.PerNameExecutor;
30a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport com.android.quicksearchbox.util.SingleThreadNamedTaskExecutor;
31185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.app.Application;
333e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.os.Handler;
343e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport android.os.Looper;
353e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
3672f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringertimport java.util.concurrent.Executor;
3772f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringertimport java.util.concurrent.Executors;
383e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertimport java.util.concurrent.ThreadFactory;
393e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
403e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringertpublic class QsbApplication extends Application {
413e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
420484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    private Handler mUiThreadHandler;
433e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private Config mConfig;
44883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    private Corpora mCorpora;
45fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    private CorpusRanker mCorpusRanker;
463e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    private ShortcutRepository mShortcutRepository;
4794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    private ShortcutRefresher mShortcutRefresher;
48a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert    private NamedTaskExecutor mSourceTaskExecutor;
4972f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    private ThreadFactory mQueryThreadFactory;
5047d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    private SuggestionsProvider mSuggestionsProvider;
51185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    private SuggestionViewFactory mSuggestionViewFactory;
52c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert    private CorpusViewFactory mCorpusViewFactory;
53ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert    private Logger mLogger;
543e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    @Override
563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public void onTerminate() {
573e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        close();
583e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        super.onTerminate();
593e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
603e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
61fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    protected void checkThread() {
62fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        if (Looper.myLooper() != Looper.getMainLooper()) {
63fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            throw new IllegalStateException("Accessed Application object from thread "
64fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert                    + Thread.currentThread().getName());
65fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        }
66fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
67fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
683e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected void close() {
69fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
70af736c70f989ebd716e0e389a28c6604b218e14fBjorn Bringert        if (mConfig != null) {
71af736c70f989ebd716e0e389a28c6604b218e14fBjorn Bringert            mConfig.close();
72af736c70f989ebd716e0e389a28c6604b218e14fBjorn Bringert            mConfig = null;
73af736c70f989ebd716e0e389a28c6604b218e14fBjorn Bringert        }
74fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        if (mCorpora != null) {
75fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            mCorpora.close();
76fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            mCorpora = null;
773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mShortcutRepository != null) {
793e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mShortcutRepository.close();
803e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mShortcutRepository = null;
813e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
823e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mSourceTaskExecutor != null) {
833e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mSourceTaskExecutor.close();
843e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mSourceTaskExecutor = null;
853e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
8647d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert        if (mSuggestionsProvider != null) {
8747d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert            mSuggestionsProvider.close();
8847d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert            mSuggestionsProvider = null;
893e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
903e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
913e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
92fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public synchronized Handler getMainThreadHandler() {
930484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        if (mUiThreadHandler == null) {
94fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            mUiThreadHandler = new Handler(Looper.getMainLooper());
950484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        }
960484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        return mUiThreadHandler;
970484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
980484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
99fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
100fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the QSB configuration object.
101fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May be called from any thread.
102fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
103fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public synchronized Config getConfig() {
1043e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mConfig == null) {
1053e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mConfig = createConfig();
1063e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return mConfig;
1083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
1103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    protected Config createConfig() {
1113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return new Config(this);
1123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1133e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
114fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
115fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the corpora.
116fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
117fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
118fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public Corpora getCorpora() {
119fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
120fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        if (mCorpora == null) {
121fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            mCorpora = createCorpora();
1223e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
123fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return mCorpora;
1243e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1253e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
126883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    protected Corpora createCorpora() {
127dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert        SearchableCorpora corpora = new SearchableCorpora(this, getConfig(), createSources(),
128dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert                createCorpusFactory());
129fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        corpora.load();
130fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return corpora;
1313e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1323e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
133883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    protected Sources createSources() {
134883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert        return new SearchableSources(this, getMainThreadHandler());
135883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    }
136883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
137883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    protected CorpusFactory createCorpusFactory() {
13872f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        int numWebCorpusThreads = getConfig().getNumWebCorpusThreads();
13972f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        return new SearchableCorpusFactory(this, createExecutorFactory(numWebCorpusThreads));
14072f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    }
14172f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert
14272f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    protected Factory<Executor> createExecutorFactory(final int numThreads) {
14372f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        final ThreadFactory threadFactory = getQueryThreadFactory();
14472f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        return new Factory<Executor>() {
14572f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert            public Executor create() {
14672f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert                return Executors.newFixedThreadPool(numThreads, threadFactory);
14772f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert            }
14872f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        };
149883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    }
150883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
151fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
152fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the corpus ranker.
153fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
154fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
155fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    public CorpusRanker getCorpusRanker() {
156fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
157fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        if (mCorpusRanker == null) {
158fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            mCorpusRanker = createCorpusRanker();
159fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        }
160fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return mCorpusRanker;
161fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
162fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
163fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    protected CorpusRanker createCorpusRanker() {
164ce4cdcf739b57563ddcdbed6944128b8c1f7522aBjorn Bringert        return new DefaultCorpusRanker(getCorpora(), getShortcutRepository());
165fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
166fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
167fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
168fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the shortcut repository.
169fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
170fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
1713e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    public ShortcutRepository getShortcutRepository() {
172fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
1733e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mShortcutRepository == null) {
1743e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mShortcutRepository = createShortcutRepository();
1753e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
1763e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return mShortcutRepository;
1773e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
1783e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
179fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    protected ShortcutRepository createShortcutRepository() {
180fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return ShortcutRepositoryImplLog.create(this, getConfig(), getCorpora(),
181fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            getShortcutRefresher(), getMainThreadHandler());
182fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    }
183fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert
184fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
185fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the shortcut refresher.
186fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
187fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
18894e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    public ShortcutRefresher getShortcutRefresher() {
189fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
19094e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        if (mShortcutRefresher == null) {
19194e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney            mShortcutRefresher = createShortcutRefresher();
19294e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        }
19394e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        return mShortcutRefresher;
19494e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    }
19594e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney
19694e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney    protected ShortcutRefresher createShortcutRefresher() {
19794e8a2be78530170f50e7895a558bf8011bbf8e8Bryan Mawhinney        // For now, ShortcutRefresher gets its own SourceTaskExecutor
19804a180b52fb4100a2f3747e795fb5d26e3207a4aBjorn Bringert        return new SourceShortcutRefresher(createSourceTaskExecutor());
1993e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2003e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
201fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
202fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the source task executor.
203fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
204fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
205a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert    public NamedTaskExecutor getSourceTaskExecutor() {
206fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
2073e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        if (mSourceTaskExecutor == null) {
2083e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert            mSourceTaskExecutor = createSourceTaskExecutor();
2093e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        }
2103e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return mSourceTaskExecutor;
2113e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2123e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
213a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert    protected NamedTaskExecutor createSourceTaskExecutor() {
2143e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        Config config = getConfig();
21572f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        ThreadFactory queryThreadFactory = getQueryThreadFactory();
216a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert        return new PerNameExecutor(SingleThreadNamedTaskExecutor.factory(queryThreadFactory));
2173e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
2183e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert
219fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
22072f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert     * Gets the query thread factory.
22172f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert     * May only be called from the main thread.
22272f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert     */
22372f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    protected ThreadFactory getQueryThreadFactory() {
22472f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        checkThread();
22572f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        if (mQueryThreadFactory == null) {
22672f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert            mQueryThreadFactory = createQueryThreadFactory();
22772f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        }
22872f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        return mQueryThreadFactory;
22972f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    }
23072f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert
23172f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    protected ThreadFactory createQueryThreadFactory() {
23272f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert        return new QueryThreadFactory(getConfig().getQueryThreadPriority());
23372f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    }
23472f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert
23572f9b08ce84d0e13daf2d1c112d4e6d1d3ada045Bjorn Bringert    /**
23647d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert     * Gets the suggestion provider.
237fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
238fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
23947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    protected SuggestionsProvider getSuggestionsProvider() {
240fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
24147d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert        if (mSuggestionsProvider == null) {
24247d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert            mSuggestionsProvider = createSuggestionsProvider();
2430484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        }
24447d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert        return mSuggestionsProvider;
2450484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
2460484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
24747d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    protected SuggestionsProvider createSuggestionsProvider() {
24882bcf002f2f736afcd6cb548c19aa4e8ac12b421Bjorn Bringert        Promoter promoter =  new ShortcutPromoter(new RankAwarePromoter());
24947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert        SuggestionsProvider provider = new SuggestionsProviderImpl(getConfig(),
2503e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                getSourceTaskExecutor(),
251fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert                getMainThreadHandler(),
2523e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert                promoter,
253f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert                getShortcutRepository(),
254f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert                getLogger());
2553e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert        return provider;
2563e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert    }
257185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
258fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
259fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the suggestion view factory.
260fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
261fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
262185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    public SuggestionViewFactory getSuggestionViewFactory() {
263fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
264185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        if (mSuggestionViewFactory == null) {
265185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert            mSuggestionViewFactory = createSuggestionViewFactory();
266185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        }
267185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        return mSuggestionViewFactory;
268185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    }
269185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
270185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    protected SuggestionViewFactory createSuggestionViewFactory() {
271185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert        return new SuggestionViewInflater(this);
272185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert    }
273185bb2e3881452c084fde44d9bee657f65881b0eBjorn Bringert
274fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
275c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert     * Gets the corpus view factory.
276c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert     * May only be called from the main thread.
277c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert     */
278c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert    public CorpusViewFactory getCorpusViewFactory() {
279c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert        checkThread();
280c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert        if (mCorpusViewFactory == null) {
281c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert            mCorpusViewFactory = createCorpusViewFactory();
282c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert        }
283c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert        return mCorpusViewFactory;
284c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert    }
285c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert
286c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert    protected CorpusViewFactory createCorpusViewFactory() {
287c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert        return new CorpusViewInflater(this);
288c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert    }
289c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert
290c5a3ecb62318a6be1d1a626a36b52829e989f740Bjorn Bringert    /**
291fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Creates a suggestions adapter.
292fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
293fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
294816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    public SuggestionsAdapter createSuggestionsAdapter() {
295816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        Config config = getConfig();
296816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        SuggestionViewFactory viewFactory = getSuggestionViewFactory();
297816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        DelayingSuggestionsAdapter adapter = new DelayingSuggestionsAdapter(viewFactory);
298816804b67619af133860a1e28e92f58bc642260dBjorn Bringert        return adapter;
299816804b67619af133860a1e28e92f58bc642260dBjorn Bringert    }
300e72a6418e84a89d2bfd4e9d22282eca95357e0daBjorn Bringert
301dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert    /**
302dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert     * Creates a footer view to add at the bottom of the search activity.
303dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert     */
304883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    public SuggestionsFooter createSuggestionsFooter() {
305dbdffd8316e75bc2813dbbcbef13d357970e8c84Bjorn Bringert        return new EmptySuggestionsFooter(this);
306883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert    }
307883c1bf364e38c5b133afb55f8493a14b65f4dd4Bjorn Bringert
308fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    /**
309fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * Gets the event logger.
310fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     * May only be called from the main thread.
311fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert     */
312ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert    public Logger getLogger() {
313fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        checkThread();
314ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert        if (mLogger == null) {
315ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert            mLogger = createLogger();
316ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert        }
317ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert        return mLogger;
318ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert    }
319ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert
320ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert    protected Logger createLogger() {
321f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert        return new EventLogLogger(this, getConfig());
322ca78085bb2127559e6f55276a307bfa857018ecaBjorn Bringert    }
3233e44ff1f2a204db3f479698cf0b3eab3d451dec2Bjorn Bringert}
324