SuggestionsProviderImpl.java revision 54af8b26e73f9aa2a01473517cf6d9980a95fe55
10484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert/*
20484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * Copyright (C) 2009 The Android Open Source Project
30484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert *
40484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
50484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * you may not use this file except in compliance with the License.
60484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * You may obtain a copy of the License at
70484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert *
80484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert *      http://www.apache.org/licenses/LICENSE-2.0
90484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert *
100484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
110484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
120484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * See the License for the specific language governing permissions and
140484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * limitations under the License.
150484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert */
160484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
170484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringertpackage com.android.quicksearchbox;
180484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
19a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport com.android.quicksearchbox.util.BatchingNamedTaskExecutor;
20f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringertimport com.android.quicksearchbox.util.Consumer;
21a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringertimport com.android.quicksearchbox.util.NamedTaskExecutor;
22a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert
230484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringertimport android.os.Handler;
240484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringertimport android.util.Log;
250484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
260484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringertimport java.util.ArrayList;
2781a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringertimport java.util.Collection;
2881a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringertimport java.util.Collections;
29ce4cdcf739b57563ddcdbed6944128b8c1f7522aBjorn Bringertimport java.util.List;
300484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
310484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert/**
3247d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert * Suggestions provider implementation.
330484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert *
340484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert * The provider will only handle a single query at a time. If a new query comes
3554af8b26e73f9aa2a01473517cf6d9980a95fe55Mathew Inwood * in, the old one is cancelled.
360484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert */
3747d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringertpublic class SuggestionsProviderImpl implements SuggestionsProvider {
380484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
39b5fc08b7f16a32d3865f44b7f26d8aaa5304a2adBjorn Bringert    private static final boolean DBG = false;
4047d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    private static final String TAG = "QSB.SuggestionsProviderImpl";
410484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
420484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    private final Config mConfig;
430484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
44a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert    private final NamedTaskExecutor mQueryExecutor;
450484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
460484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    private final Handler mPublishThread;
470484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
480484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    private final Promoter mPromoter;
490484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
5047d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    private final ShortcutRepository mShortcutRepo;
5147d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert
5253bf1409474f26ab0f3754ee9b4d2de901a6be00Bryan Mawhinney    private final ShouldQueryStrategy mShouldQueryStrategy = new ShouldQueryStrategy();
5353bf1409474f26ab0f3754ee9b4d2de901a6be00Bryan Mawhinney
5439bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney    private final Corpora mCorpora;
5539bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney
5681a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert    private final CorpusRanker mCorpusRanker;
5781a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert
5881a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert    private final Logger mLogger;
5981a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert
60a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert    private BatchingNamedTaskExecutor mBatchingExecutor;
6127d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney
6247d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    public SuggestionsProviderImpl(Config config,
63a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert            NamedTaskExecutor queryExecutor,
640484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert            Handler publishThread,
6547d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert            Promoter promoter,
66f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert            ShortcutRepository shortcutRepo,
6739bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney            Corpora corpora,
6881a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert            CorpusRanker corpusRanker,
69f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert            Logger logger) {
700484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        mConfig = config;
710484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        mQueryExecutor = queryExecutor;
720484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        mPublishThread = publishThread;
730484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        mPromoter = promoter;
7447d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert        mShortcutRepo = shortcutRepo;
7539bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        mCorpora = corpora;
7681a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        mCorpusRanker = corpusRanker;
7781a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        mLogger = logger;
780484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
790484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
800484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    public void close() {
810484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        cancelPendingTasks();
820484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
830484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
840484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    /**
850484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert     * Cancels all pending query tasks.
860484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert     */
870484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    private void cancelPendingTasks() {
8827d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        if (mBatchingExecutor != null) {
8927d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney            mBatchingExecutor.cancelPendingTasks();
9027d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney            mBatchingExecutor = null;
9127d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        }
920484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
930484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
9481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert    protected SuggestionCursor getShortcutsForQuery(String query, Corpus singleCorpus,
956d5cbd67f7a5f824babb5c892b0f30bfd9f4ff23Bjorn Bringert            int maxShortcuts) {
9647d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert        if (mShortcutRepo == null) return null;
9781a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        Collection<Corpus> allowedCorpora = mCorpora.getEnabledCorpora();
9881a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        return mShortcutRepo.getShortcutsForQuery(query, allowedCorpora, maxShortcuts);
9947d02f7285794bb39b2a2d828d32b5329dd8ecb0Bjorn Bringert    }
1000484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
1010484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    /**
1020484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert     * Gets the sources that should be queried for the given query.
1030484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert     */
10481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert    private List<Corpus> getCorporaToQuery(String query, Corpus singleCorpus) {
10581a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        if (singleCorpus != null) return Collections.singletonList(singleCorpus);
10681a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        List<Corpus> orderedCorpora = mCorpusRanker.getRankedCorpora();
107fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        ArrayList<Corpus> corporaToQuery = new ArrayList<Corpus>(orderedCorpora.size());
108fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        for (Corpus corpus : orderedCorpora) {
109fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            if (shouldQueryCorpus(corpus, query)) {
110fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert                corporaToQuery.add(corpus);
1110484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert            }
1120484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        }
113fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return corporaToQuery;
1140484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
1150484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
116fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    protected boolean shouldQueryCorpus(Corpus corpus, String query) {
117503aceaac1aad820f2958a03f7327df18a07f713Bryan Mawhinney        if (query.length() == 0 && !corpus.isWebCorpus()) {
118503aceaac1aad820f2958a03f7327df18a07f713Bryan Mawhinney            // Only the web corpus sees zero length queries.
119503aceaac1aad820f2958a03f7327df18a07f713Bryan Mawhinney            return false;
120503aceaac1aad820f2958a03f7327df18a07f713Bryan Mawhinney        }
121fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        return mShouldQueryStrategy.shouldQueryCorpus(corpus, query);
1220484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
1230484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
124fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert    private void updateShouldQueryStrategy(CorpusResult cursor) {
12527d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        if (cursor.getCount() == 0) {
126fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert            mShouldQueryStrategy.onZeroResults(cursor.getCorpus(),
12727d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney                    cursor.getUserQuery());
12827d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        }
12927d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney    }
13027d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney
13181a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert    public Suggestions getSuggestions(String query, Corpus singleCorpus, int maxSuggestions) {
1320484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        if (DBG) Log.d(TAG, "getSuggestions(" + query + ")");
1330484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        cancelPendingTasks();
13481a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        List<Corpus> corporaToQuery = getCorporaToQuery(query, singleCorpus);
1350484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        final Suggestions suggestions = new Suggestions(mPromoter,
136e6f46632869a288c82b75187af166931f82a6e12Bryan Mawhinney                maxSuggestions,
1370484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert                query,
13839bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                corporaToQuery.size());
1396d5cbd67f7a5f824babb5c892b0f30bfd9f4ff23Bjorn Bringert        int maxShortcuts = mConfig.getMaxShortcutsReturned();
14081a0897ff9685f3313c58294bf7973700c468b2bBjorn Bringert        SuggestionCursor shortcuts = getShortcutsForQuery(query, singleCorpus, maxShortcuts);
1410484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        if (shortcuts != null) {
1420484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert            suggestions.setShortcuts(shortcuts);
1430484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        }
1440484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
1450484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        // Fast path for the zero sources case
146fde948e69f59589cf0d217ea414af7947de600bbBjorn Bringert        if (corporaToQuery.size() == 0) {
1470484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert            return suggestions;
1480484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        }
1490484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
15039bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        int initialBatchSize = countDefaultCorpora(corporaToQuery);
15139bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        initialBatchSize = Math.min(initialBatchSize, mConfig.getNumPromotedSources());
15239bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        if (initialBatchSize == 0) {
15339bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney            initialBatchSize = mConfig.getNumPromotedSources();
15439bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        }
15539bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney
15639bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        mBatchingExecutor = new BatchingNamedTaskExecutor(mQueryExecutor);
15727d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney
15827d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        SuggestionCursorReceiver receiver = new SuggestionCursorReceiver(
15939bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                mBatchingExecutor, suggestions, initialBatchSize);
1600484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
1610484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        int maxResultsPerSource = mConfig.getMaxResultsPerSource();
162f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert        QueryTask.startQueries(query, maxResultsPerSource, corporaToQuery, mBatchingExecutor,
163f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                mPublishThread, receiver);
16439bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        mBatchingExecutor.executeNextBatch(initialBatchSize);
1650484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
1660484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert        return suggestions;
1670484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
1680484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
16939bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney    private int countDefaultCorpora(List<Corpus> corpora) {
17039bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        int count = 0;
17139bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        for (Corpus corpus : corpora) {
17239bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney            if (mCorpora.isCorpusDefaultEnabled(corpus)) {
17339bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                count++;
17439bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney            }
17539bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        }
17639bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        return count;
17739bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney    }
17839bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney
179f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert    private class SuggestionCursorReceiver implements Consumer<CorpusResult> {
180a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert        private final BatchingNamedTaskExecutor mExecutor;
18127d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        private final Suggestions mSuggestions;
18227d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney
18339bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney        private int mCountAtWhichToExecuteNextBatch;
18439bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney
185a48af083ff81555261f334a1e050eae3b02a746cBjorn Bringert        public SuggestionCursorReceiver(BatchingNamedTaskExecutor executor,
18639bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                Suggestions suggestions, int initialBatchSize) {
18727d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney            mExecutor = executor;
18827d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney            mSuggestions = suggestions;
18939bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney            mCountAtWhichToExecuteNextBatch = initialBatchSize;
19027d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        }
19127d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney
192f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert        public boolean consume(CorpusResult cursor) {
19327d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney            updateShouldQueryStrategy(cursor);
194f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            mSuggestions.addCorpusResult(cursor);
195f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            if (!mSuggestions.isClosed()) {
196f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert                executeNextBatchIfNeeded();
197f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            }
198f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert            if (cursor != null && mLogger != null) {
199f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert                mLogger.logLatency(cursor);
200f95ce100dcbc77794b79b0187c566bb58b5978d3Bjorn Bringert            }
201f252dc7a25ba08b973ecc1cfbbce58eb78d42167Bjorn Bringert            return true;
20227d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        }
20327d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney
20427d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        private void executeNextBatchIfNeeded() {
20539bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney            if (mSuggestions.getSourceCount() == mCountAtWhichToExecuteNextBatch) {
20627d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney                // We've just finished one batch
20727d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney                if (mSuggestions.getPromoted().getCount() < mConfig.getMaxPromotedSuggestions()) {
20827d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney                    // But we still don't have enough results, ask for more
20939bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                    int nextBatchSize = mConfig.getNumPromotedSources();
21039bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                    mCountAtWhichToExecuteNextBatch += nextBatchSize;
21139bbcdc1a485ded93059de4a3f70bfda85e9f304Bryan Mawhinney                    mExecutor.executeNextBatch(nextBatchSize);
21227d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney                }
21327d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney            }
21427d3d4eb3b0414cf7001020d8ddcfdde81fd516bBryan Mawhinney        }
2150484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert    }
2160484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert
2170484fb4d652bfa9d5c7fb238a7cec1a6f2244e44Bjorn Bringert}
218