15683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal/*
25683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * Copyright (C) 2015 The Android Open Source Project
35683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal *
45683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
55683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * you may not use this file except in compliance with the License.
65683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * You may obtain a copy of the License at
75683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal *
85683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
95683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal *
105683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * Unless required by applicable law or agreed to in writing, software
115683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
125683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * See the License for the specific language governing permissions and
145683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal * limitations under the License.
155683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal */
165f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungpackage com.android.launcher3.allapps;
1793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
1893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport android.content.Context;
197c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyalimport android.os.Process;
200fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschlerimport android.support.annotation.NonNull;
210fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschlerimport android.support.annotation.Nullable;
2213eb527b5ae7f564e3ace6137a8d466636d87188Winson Chungimport android.util.Log;
236c56c68555dcb3d99b05d5faecd582a1f683cc92Sunny Goyal
245f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.AppInfo;
255f4e0fdd2e4edeb9211e2dcd1c99497f175731f8Winson Chungimport com.android.launcher3.Launcher;
2693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport com.android.launcher3.compat.AlphabeticIndexCompat;
273d706ad70365052e3224fc4f4b0e7d1f5e8abf22Sunny Goyalimport com.android.launcher3.config.FeatureFlags;
280fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschlerimport com.android.launcher3.discovery.AppDiscoveryAppInfo;
290fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschlerimport com.android.launcher3.discovery.AppDiscoveryItem;
300fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschlerimport com.android.launcher3.discovery.AppDiscoveryUpdateState;
315183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyalimport com.android.launcher3.util.ComponentKey;
328ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschlerimport com.android.launcher3.util.ComponentKeyMapper;
33d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyalimport com.android.launcher3.util.LabelComparator;
3493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
3593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport java.util.ArrayList;
3693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport java.util.Collections;
37c517f4ce65cfbb3c52231262cf24847820213d29Winson Chungimport java.util.HashMap;
3893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungimport java.util.List;
39a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chungimport java.util.Locale;
40a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chungimport java.util.Map;
41a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chungimport java.util.TreeMap;
4293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
43c517f4ce65cfbb3c52231262cf24847820213d29Winson Chung/**
4493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung * The alphabetically sorted list of applications.
4593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung */
4693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chungpublic class AlphabeticalAppsList {
4793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
4813eb527b5ae7f564e3ace6137a8d466636d87188Winson Chung    public static final String TAG = "AlphabeticalAppsList";
4913eb527b5ae7f564e3ace6137a8d466636d87188Winson Chung    private static final boolean DEBUG = false;
508f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung    private static final boolean DEBUG_PREDICTIONS = false;
5113eb527b5ae7f564e3ace6137a8d466636d87188Winson Chung
52d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson    private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION = 0;
53d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson    private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1;
54d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
55d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson    private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS;
56d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
570fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private AppDiscoveryUpdateState mAppDiscoveryUpdateState;
580fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
5993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
6099d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     * Info about a fast scroller section, depending if sections are merged, the fast scroller
6199d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     * sections will not be the same set as the section headers.
6299d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     */
6399d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung    public static class FastScrollSectionInfo {
6499d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        // The section name
6599d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        public String sectionName;
6699d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        // The AdapterItem to scroll to for this section
67b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        public AdapterItem fastScrollToItem;
68b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        // The touch fraction that should map to this fast scroll section info
69b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        public float touchFraction;
7099d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung
71b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        public FastScrollSectionInfo(String sectionName) {
7299d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung            this.sectionName = sectionName;
739121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung        }
749121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung    }
759121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung
769121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung    /**
779121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung     * Info about a particular adapter item (can be either section or app)
789121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung     */
799121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung    public static class AdapterItem {
80208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        /** Common properties */
819121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung        // The index of this adapter item in the list
829121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung        public int position;
83208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        // The type of this item
84208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        public int viewType;
85208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
8699d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        /** App-only properties */
8799d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        // The section name of this app.  Note that there can be multiple items with different
8899d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        // sectionNames in the same section
8999d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        public String sectionName = null;
90d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        // The row that this item shows up on
91d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson        public int rowIndex;
92b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        // The index of this app in the row
93b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        public int rowAppIndex;
9499d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        // The associated AppInfo for the app
9599d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        public AppInfo appInfo = null;
9699d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        // The index of this app not including sections
9799d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        public int appIndex = -1;
989121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung
992a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal        public static AdapterItem asPredictedApp(int pos, String sectionName, AppInfo appInfo,
1002a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                int appIndex) {
1012a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal            AdapterItem item = asApp(pos, sectionName, appInfo, appIndex);
102c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.viewType = AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON;
103208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung            return item;
104208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        }
105208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
1062a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal        public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo,
1072a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                int appIndex) {
1089121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            AdapterItem item = new AdapterItem();
109c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.viewType = AllAppsGridAdapter.VIEW_TYPE_ICON;
1109121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            item.position = pos;
1119121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            item.sectionName = sectionName;
1129121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            item.appInfo = appInfo;
1139121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            item.appIndex = appIndex;
1149121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            return item;
1159121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung        }
116bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung
1170fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        public static AdapterItem asDiscoveryItem(int pos, String sectionName, AppInfo appInfo,
1180fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                int appIndex) {
1190fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            AdapterItem item = new AdapterItem();
1200fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.viewType = AllAppsGridAdapter.VIEW_TYPE_DISCOVERY_ITEM;
1210fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.position = pos;
1220fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.sectionName = sectionName;
1230fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.appInfo = appInfo;
1240fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.appIndex = appIndex;
1250fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            return item;
1260fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        }
1270fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
128bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        public static AdapterItem asEmptySearch(int pos) {
129bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            AdapterItem item = new AdapterItem();
130c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.viewType = AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH;
131bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            item.position = pos;
132bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            return item;
133bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        }
134bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung
135c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        public static AdapterItem asPredictionDivider(int pos) {
136bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            AdapterItem item = new AdapterItem();
137c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.viewType = AllAppsGridAdapter.VIEW_TYPE_PREDICTION_DIVIDER;
138c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.position = pos;
139c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            return item;
140c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        }
141c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller
142c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller        public static AdapterItem asMarketDivider(int pos) {
143c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            AdapterItem item = new AdapterItem();
144c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.viewType = AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET_DIVIDER;
145bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            item.position = pos;
146bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            return item;
147bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        }
148bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung
1490fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        public static AdapterItem asLoadingDivider(int pos) {
1500fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            AdapterItem item = new AdapterItem();
1510fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.viewType = AllAppsGridAdapter.VIEW_TYPE_APPS_LOADING_DIVIDER;
1520fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            item.position = pos;
1530fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            return item;
1540fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        }
1550fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
156bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        public static AdapterItem asMarketSearch(int pos) {
157bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            AdapterItem item = new AdapterItem();
158c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller            item.viewType = AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET;
159bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            item.position = pos;
160bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            return item;
161bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        }
16293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
16393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
1640fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private final Launcher mLauncher;
1653abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung
1663abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    // The set of apps from the system not including predictions
1675683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal    private final List<AppInfo> mApps = new ArrayList<>();
1685183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal    private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>();
1695183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal
1703abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    // The set of filtered apps with the current filter
1710fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private final List<AppInfo> mFilteredApps = new ArrayList<>();
1723abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    // The current set of adapter items
1730fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private final ArrayList<AdapterItem> mAdapterItems = new ArrayList<>();
1743abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    // The set of sections that we allow fast-scrolling to (includes non-merged sections)
1750fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private final List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
1763abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    // The set of predicted app component names
1778ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler    private final List<ComponentKeyMapper<AppInfo>> mPredictedAppComponents = new ArrayList<>();
1783abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    // The set of predicted apps resolved from the component names and the current set of apps
1790fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private final List<AppInfo> mPredictedApps = new ArrayList<>();
1800fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private final List<AppDiscoveryAppInfo> mDiscoveredApps = new ArrayList<>();
1810fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
1825683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal    // The of ordered component names as a result of a search query
1835183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal    private ArrayList<ComponentKey> mSearchResults;
18413eb527b5ae7f564e3ace6137a8d466636d87188Winson Chung    private HashMap<CharSequence, String> mCachedSectionNames = new HashMap<>();
18542e28092b336bf89bee94c61e2cd327e1d8ec882Sunny Goyal    private AllAppsGridAdapter mAdapter;
18693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private AlphabeticIndexCompat mIndexer;
187d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal    private AppInfoComparator mAppNameComparator;
18883f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung    private int mNumAppsPerRow;
189208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung    private int mNumPredictedAppsPerRow;
190b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    private int mNumAppRowsInAdapter;
19193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
192ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public AlphabeticalAppsList(Context context) {
1932fd020860533e18c64a93d14d11cb2d34bc9cbafTony        mLauncher = Launcher.getLauncher(context);
19493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        mIndexer = new AlphabeticIndexCompat(context);
195d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        mAppNameComparator = new AppInfoComparator(context);
19683f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung    }
19783f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung
19883f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung    /**
199fbc5b18626ae2e158e39c59606455124cfa8127dWinson Chung     * Sets the number of apps per row.
20083f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung     */
2012a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal    public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
202208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        mNumAppsPerRow = numAppsPerRow;
203208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        mNumPredictedAppsPerRow = numPredictedAppsPerRow;
204208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
205ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        updateAdapterItems();
20693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
20793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
20893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
20993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Sets the adapter to notify when this dataset changes.
21093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
21142e28092b336bf89bee94c61e2cd327e1d8ec882Sunny Goyal    public void setAdapter(AllAppsGridAdapter adapter) {
21293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        mAdapter = adapter;
21393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
21493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
21593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
216ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     * Returns all the apps.
217ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung     */
218ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    public List<AppInfo> getApps() {
219ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung        return mApps;
220ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    }
221ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung
222ef7f874a889b609bd34e692b9c9a1f8cefd1ea95Winson Chung    /**
2234e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda     * Returns the predicted apps.
2244e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda     */
2254e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda    public List<AppInfo> getPredictedApps() {
2264e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda        return mPredictedApps;
2274e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda    }
2284e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda
2294e11c2738a346fe2859c2d03e3133671e5da49ecJon Miranda    /**
23099d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     * Returns fast scroller sections of all the current filtered applications.
23199d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung     */
23299d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung    public List<FastScrollSectionInfo> getFastScrollerSections() {
23399d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung        return mFastScrollerSections;
23499d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung    }
23599d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung
23699d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung    /**
23793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Returns the current filtered list of applications broken down into their sections.
23893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
2399121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung    public List<AdapterItem> getAdapterItems() {
2403abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        return mAdapterItems;
24193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
24293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
24393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
244bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung     * Returns the number of rows of applications (not including predictions)
24593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
246bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung    public int getNumAppRows() {
247bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        return mNumAppRowsInAdapter;
24893f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
24993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
25093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
251bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung     * Returns the number of applications in this list.
252b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung     */
253bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung    public int getNumFilteredApps() {
254bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        return mFilteredApps.size();
255b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    }
256b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
257b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung    /**
25883f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung     * Returns whether there are is a filter set.
25983f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung     */
26083f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung    public boolean hasFilter() {
2615683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        return (mSearchResults != null);
26283f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung    }
26383f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung
26483f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung    /**
265888b3a10bf1e99192f12c844ee275c6f360d6b34Winson Chung     * Returns whether there are no filtered results.
266888b3a10bf1e99192f12c844ee275c6f360d6b34Winson Chung     */
267888b3a10bf1e99192f12c844ee275c6f360d6b34Winson Chung    public boolean hasNoFilteredResults() {
2685683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        return (mSearchResults != null) && mFilteredApps.isEmpty();
269888b3a10bf1e99192f12c844ee275c6f360d6b34Winson Chung    }
270888b3a10bf1e99192f12c844ee275c6f360d6b34Winson Chung
2710fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    boolean shouldShowEmptySearch() {
2720fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        return hasNoFilteredResults() && !isAppDiscoveryRunning() && mDiscoveredApps.isEmpty();
2730fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    }
2740fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
275888b3a10bf1e99192f12c844ee275c6f360d6b34Winson Chung    /**
2765683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal     * Sets the sorted list of filtered components.
27793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
278bb702584fa551fab8cffbb0ae5459d9efd16ce2aSunny Goyal    public boolean setOrderedFilter(ArrayList<ComponentKey> f) {
2795683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        if (mSearchResults != f) {
280bb702584fa551fab8cffbb0ae5459d9efd16ce2aSunny Goyal            boolean same = mSearchResults != null && mSearchResults.equals(f);
2815683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal            mSearchResults = f;
2823abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            updateAdapterItems();
283bb702584fa551fab8cffbb0ae5459d9efd16ce2aSunny Goyal            return !same;
28483f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung        }
285bb702584fa551fab8cffbb0ae5459d9efd16ce2aSunny Goyal        return false;
28693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
28793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
2880fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    public void onAppDiscoverySearchUpdate(@Nullable AppDiscoveryItem app,
2890fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                @NonNull AppDiscoveryUpdateState state) {
2900fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        mAppDiscoveryUpdateState = state;
2910fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        switch (state) {
2920fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            case START:
2930fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                mDiscoveredApps.clear();
2940fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                break;
2950fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            case UPDATE:
296853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                mDiscoveredApps.add(new AppDiscoveryAppInfo(app));
2970fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                break;
2980fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        }
2990fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        updateAdapterItems();
3000fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    }
3010fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
3028ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler    private List<AppInfo> processPredictedAppComponents(List<ComponentKeyMapper<AppInfo>> components) {
3037653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        if (mComponentToAppMap.isEmpty()) {
3047653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            // Apps have not been bound yet.
3057653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            return Collections.emptyList();
3067653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        }
3077653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda
3087653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        List<AppInfo> predictedApps = new ArrayList<>();
3098ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler        for (ComponentKeyMapper<AppInfo> mapper : components) {
3108ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler            AppInfo info = mapper.getItem(mComponentToAppMap);
3117653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            if (info != null) {
3127653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                predictedApps.add(info);
3137653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            } else {
3147653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                if (FeatureFlags.IS_DOGFOOD_BUILD) {
3158ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                    Log.e(TAG, "Predicted app not found: " + mapper);
3167653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                }
3177653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            }
3187653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            // Stop at the number of predicted apps
3197653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            if (predictedApps.size() == mNumPredictedAppsPerRow) {
3207653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                break;
3217653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            }
3227653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        }
3237653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        return predictedApps;
3247653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda    }
3257653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda
32693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
3277653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * Sets the current set of predicted apps.
3287653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     *
3297653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * This can be called before we get the full set of applications, we should merge the results
3307653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * only in onAppsUpdated() which is idempotent.
3317653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     *
3327653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * If the number of predicted apps is the same as the previous list of predicted apps,
3337653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * we can optimize by swapping them in place.
3344ac30068732c7216288999d255a823adb7ca7c12Winson Chung     */
3358ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler    public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
336208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        mPredictedAppComponents.clear();
337208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung        mPredictedAppComponents.addAll(apps);
3387653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda
3397653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        List<AppInfo> newPredictedApps = processPredictedAppComponents(apps);
3407653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        // We only need to do work if any of the visible predicted apps have changed.
3417653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        if (!newPredictedApps.equals(mPredictedApps)) {
3427653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            if (newPredictedApps.size() == mPredictedApps.size()) {
3437653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                swapInNewPredictedApps(newPredictedApps);
3447653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            } else {
3457653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                // We need to update the appIndex of all the items.
3467653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda                onAppsUpdated();
3477653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            }
3487653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        }
3497653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda    }
3507653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda
3517653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda    /**
3527653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * Swaps out the old predicted apps with the new predicted apps, in place. This optimization
3537653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * allows us to skip an entire relayout that would otherwise be called by notifyDataSetChanged.
3547653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     *
3557653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     * Note: This should only be called if the # of predicted apps is the same.
3567653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     *       This method assumes that predicted apps are the first items in the adapter.
3577653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda     */
3587653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda    private void swapInNewPredictedApps(List<AppInfo> apps) {
3597653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        mPredictedApps.clear();
3607653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        mPredictedApps.addAll(apps);
3617653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda
3627653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        int size = apps.size();
3637653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        for (int i = 0; i < size; ++i) {
3647653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            AppInfo info = apps.get(i);
3657653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            AdapterItem appItem = AdapterItem.asPredictedApp(i, "", info, i);
366bb10fa8fc2f125245163a50bf6cd04ff03bdfac4Jon Miranda            appItem.rowAppIndex = i;
3677653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            mAdapterItems.set(i, appItem);
3687653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            mFilteredApps.set(i, info);
3697653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            mAdapter.notifyItemChanged(i);
3707653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda        }
3714ac30068732c7216288999d255a823adb7ca7c12Winson Chung    }
3724ac30068732c7216288999d255a823adb7ca7c12Winson Chung
3734ac30068732c7216288999d255a823adb7ca7c12Winson Chung    /**
37493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Sets the current set of apps.
37593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
37693f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    public void setApps(List<AppInfo> apps) {
3775183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        mComponentToAppMap.clear();
378b23980cc0e56b5d3f5ac0ca7714eca6479e502aeSunny Goyal        addOrUpdateApps(apps);
37993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
38093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
38193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
382b23980cc0e56b5d3f5ac0ca7714eca6479e502aeSunny Goyal     * Adds or updates existing apps in the list
38393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
384b23980cc0e56b5d3f5ac0ca7714eca6479e502aeSunny Goyal    public void addOrUpdateApps(List<AppInfo> apps) {
3855183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        for (AppInfo app : apps) {
3865183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal            mComponentToAppMap.put(app.toComponentKey(), app);
38793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        }
388f50c12788c1ebbd28e9bc45575601540983c6562Winson Chung        onAppsUpdated();
38993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
39093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
39193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
39293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Removes some apps from the list.
39393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
39493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    public void removeApps(List<AppInfo> apps) {
3955183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        for (AppInfo app : apps) {
3965183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal            mComponentToAppMap.remove(app.toComponentKey());
39793f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        }
398f50c12788c1ebbd28e9bc45575601540983c6562Winson Chung        onAppsUpdated();
39993f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    }
40093f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung
40193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    /**
40293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     * Updates internals when the set of apps are updated.
40393f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung     */
40493f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung    private void onAppsUpdated() {
405f50c12788c1ebbd28e9bc45575601540983c6562Winson Chung        // Sort the list of apps
4065183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        mApps.clear();
4075183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        mApps.addAll(mComponentToAppMap.values());
408d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal        Collections.sort(mApps, mAppNameComparator);
409a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung
410a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        // As a special case for some languages (currently only Simplified Chinese), we may need to
411a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        // coalesce sections
4122e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        Locale curLocale = mLauncher.getResources().getConfiguration().locale;
413a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        boolean localeRequiresSectionSorting = curLocale.equals(Locale.SIMPLIFIED_CHINESE);
414a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        if (localeRequiresSectionSorting) {
415d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            // Compute the section headers. We use a TreeMap with the section name comparator to
416a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung            // ensure that the sections are ordered when we iterate over it later
417d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            TreeMap<String, ArrayList<AppInfo>> sectionMap = new TreeMap<>(new LabelComparator());
418a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung            for (AppInfo info : mApps) {
419a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                // Add the section to the cache
4203abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung                String sectionName = getAndUpdateCachedSectionName(info.title);
421a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung
422a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                // Add it to the mapping
423a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                ArrayList<AppInfo> sectionApps = sectionMap.get(sectionName);
424a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                if (sectionApps == null) {
425a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                    sectionApps = new ArrayList<>();
426a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                    sectionMap.put(sectionName, sectionApps);
427a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                }
428a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                sectionApps.add(info);
429a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung            }
430208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
4313abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            // Add each of the section apps to the list in order
432d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal            mApps.clear();
433208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung            for (Map.Entry<String, ArrayList<AppInfo>> entry : sectionMap.entrySet()) {
434d164b7f4abcba6cc965c2264257569f88ad5e4a5Sunny Goyal                mApps.addAll(entry.getValue());
435208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung            }
436a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        } else {
437a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung            // Just compute the section headers for use below
438a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung            for (AppInfo info : mApps) {
439a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung                // Add the section to the cache
4403abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung                getAndUpdateCachedSectionName(info.title);
4413abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            }
4423abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        }
4433abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung
4443abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        // Recompose the set of adapter items from the current set of apps
4453abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        updateAdapterItems();
4463abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    }
4473abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung
4483abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    /**
4493abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung     * Updates the set of filtered apps with the current filter.  At this point, we expect
4503abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung     * mCachedSectionNames to have been calculated for the set of all apps in mApps.
4513abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung     */
4523abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    private void updateAdapterItems() {
4530fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        refillAdapterItems();
4540fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        refreshRecyclerView();
4550fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    }
4560fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
4570fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private void refreshRecyclerView() {
4580fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        if (mAdapter != null) {
4590fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            mAdapter.notifyDataSetChanged();
4600fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        }
4610fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    }
4620fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
4630fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    private void refillAdapterItems() {
4643abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        String lastSectionName = null;
4653abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        FastScrollSectionInfo lastFastScrollerSectionInfo = null;
4663abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        int position = 0;
4673abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        int appIndex = 0;
4683abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung
4693abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        // Prepare to update the list of sections, filtered apps, etc.
4703abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        mFilteredApps.clear();
4713abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        mFastScrollerSections.clear();
4723abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        mAdapterItems.clear();
4733abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung
4748f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        if (DEBUG_PREDICTIONS) {
4758f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung            if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) {
4768ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
4778ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                        Process.myUserHandle())));
4788ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
4798ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                        Process.myUserHandle())));
4808ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
4818ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                        Process.myUserHandle())));
4828ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                mPredictedAppComponents.add(new ComponentKeyMapper<AppInfo>(new ComponentKey(mApps.get(0).componentName,
4838ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler                        Process.myUserHandle())));
4848f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung            }
4858f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung        }
4868f1eff7b6cc8621888ee46605c32e601f80a890bWinson Chung
4873abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        // Process the predicted app components
4883abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        mPredictedApps.clear();
4893abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) {
4907653a60c74e9babfda1c3754eb4f3060b6e40990Jon Miranda            mPredictedApps.addAll(processPredictedAppComponents(mPredictedAppComponents));
4913abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung
4923abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            if (!mPredictedApps.isEmpty()) {
4931ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                // Add a section for the predictions
494b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                lastFastScrollerSectionInfo = new FastScrollSectionInfo("");
495b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                mFastScrollerSections.add(lastFastScrollerSectionInfo);
4961ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung
4971ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                // Add the predicted app items
4981ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                for (AppInfo info : mPredictedApps) {
4992a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                    AdapterItem appItem = AdapterItem.asPredictedApp(position++, "", info,
5002a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                            appIndex++);
5012a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal                    if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
5021ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                        lastFastScrollerSectionInfo.fastScrollToItem = appItem;
5031ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                    }
5041ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                    mAdapterItems.add(appItem);
5051ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                    mFilteredApps.add(info);
5061ae7a5018b48dba562bc18821f0f1e778192ee85Winson Chung                }
507c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller
508c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                mAdapterItems.add(AdapterItem.asPredictionDivider(position++));
509a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung            }
510a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        }
5114ac30068732c7216288999d255a823adb7ca7c12Winson Chung
5124ac30068732c7216288999d255a823adb7ca7c12Winson Chung        // Recreate the filtered and sectioned apps (for convenience for the grid layout) from the
513a3499dc019a677efb008d926b2cd9a5ad0bc0ca0Winson Chung        // ordered set of sections
514b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        for (AppInfo info : getFiltersAppInfos()) {
5153abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            String sectionName = getAndUpdateCachedSectionName(info.title);
5169121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung
5174ac30068732c7216288999d255a823adb7ca7c12Winson Chung            // Create a new section if the section names do not match
5182a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal            if (!sectionName.equals(lastSectionName)) {
51999d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung                lastSectionName = sectionName;
520b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName);
52199d96ba6c8e3258f7d99a33d49da2aeb0da5d862Winson Chung                mFastScrollerSections.add(lastFastScrollerSectionInfo);
52293f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung            }
5239121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung
5249121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            // Create an app item
5252a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal            AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
5262a65020da135037b8ee9408e7efb992eef02a896Sunny Goyal            if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
527b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                lastFastScrollerSectionInfo.fastScrollToItem = appItem;
5289121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            }
5293abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            mAdapterItems.add(appItem);
5309121fbffafe0b90a23768e5ebc5fffab2a2175c2Winson Chung            mFilteredApps.add(info);
53193f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung        }
53283f59abc9c566da5deb98afe7ea35cfb061f2920Winson Chung
533bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        if (hasFilter()) {
5340fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler            if (isAppDiscoveryRunning() || mDiscoveredApps.size() > 0) {
5350fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                mAdapterItems.add(AdapterItem.asLoadingDivider(position++));
5360fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                // Append all app discovery results
5370fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                for (int i = 0; i < mDiscoveredApps.size(); i++) {
5380fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    AppDiscoveryAppInfo appDiscoveryAppInfo = mDiscoveredApps.get(i);
539853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                    if (appDiscoveryAppInfo.isRecent) {
540853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                        // already handled in getFilteredAppInfos()
541853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                        continue;
542853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                    }
5430fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    AdapterItem item = AdapterItem.asDiscoveryItem(position++,
5440fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                            "", appDiscoveryAppInfo, appIndex++);
5450fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    mAdapterItems.add(item);
5460fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                }
5470fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
5480fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                if (!isAppDiscoveryRunning()) {
5490fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    mAdapterItems.add(AdapterItem.asMarketSearch(position++));
5500fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                }
551bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            } else {
5520fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                // Append the search market item
5530fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                if (hasNoFilteredResults()) {
5540fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    mAdapterItems.add(AdapterItem.asEmptySearch(position++));
5550fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                } else {
5560fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                    mAdapterItems.add(AdapterItem.asMarketDivider(position++));
5570fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                }
5580fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                mAdapterItems.add(AdapterItem.asMarketSearch(position++));
559bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung            }
560bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung        }
561bedf9232eb67a420f0372d3ca135ca13194e603bWinson Chung
562b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        if (mNumAppsPerRow != 0) {
563b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            // Update the number of rows in the adapter after we do all the merging (otherwise, we
564b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            // would have to shift the values again)
565b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            int numAppsInSection = 0;
566b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            int numAppsInRow = 0;
567b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            int rowIndex = -1;
568b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            for (AdapterItem item : mAdapterItems) {
569b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                item.rowIndex = 0;
570c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                if (AllAppsGridAdapter.isDividerViewType(item.viewType)) {
571b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    numAppsInSection = 0;
572c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                } else if (AllAppsGridAdapter.isIconViewType(item.viewType)) {
573b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    if (numAppsInSection % mNumAppsPerRow == 0) {
574b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                        numAppsInRow = 0;
575b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                        rowIndex++;
576b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    }
577b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    item.rowIndex = rowIndex;
578b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    item.rowAppIndex = numAppsInRow;
579b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    numAppsInSection++;
580b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                    numAppsInRow++;
581b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung                }
582b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            }
583b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            mNumAppRowsInAdapter = rowIndex + 1;
584b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
585d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson            // Pre-calculate all the fast scroller fractions
586d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson            switch (mFastScrollDistributionMode) {
587d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION:
588d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    float rowFraction = 1f / mNumAppRowsInAdapter;
589d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    for (FastScrollSectionInfo info : mFastScrollerSections) {
590d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        AdapterItem item = info.fastScrollToItem;
591c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                        if (!AllAppsGridAdapter.isIconViewType(item.viewType)) {
592d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                            info.touchFraction = 0f;
593d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                            continue;
594d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        }
595d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson
596d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        float subRowFraction = item.rowAppIndex * (rowFraction / mNumAppsPerRow);
597d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        info.touchFraction = item.rowIndex * rowFraction + subRowFraction;
598d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    }
599d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    break;
600d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS:
601d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    float perSectionTouchFraction = 1f / mFastScrollerSections.size();
602d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    float cumulativeTouchFraction = 0f;
603d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    for (FastScrollSectionInfo info : mFastScrollerSections) {
604d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        AdapterItem item = info.fastScrollToItem;
605c2a20ff0a87f58b2be66f067b0024db7ff5185d3Peter Schiller                        if (!AllAppsGridAdapter.isIconViewType(item.viewType)) {
606d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                            info.touchFraction = 0f;
607d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                            continue;
608d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        }
609d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        info.touchFraction = cumulativeTouchFraction;
610d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                        cumulativeTouchFraction += perSectionTouchFraction;
611d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    }
612d2eb49e4c3bb37d35e72c36d8a308262b690075fWinson                    break;
613b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung            }
614b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung        }
6150fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    }
616b1777447d9b9700b48f8060f8b318f2363c43e8dWinson Chung
6170fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler    public boolean isAppDiscoveryRunning() {
6180fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler        return mAppDiscoveryUpdateState == AppDiscoveryUpdateState.START
6190fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler                || mAppDiscoveryUpdateState == AppDiscoveryUpdateState.UPDATE;
620208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung    }
621208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung
6225683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal    private List<AppInfo> getFiltersAppInfos() {
6235683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        if (mSearchResults == null) {
6245683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal            return mApps;
6255683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        }
6265683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal
6275683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        ArrayList<AppInfo> result = new ArrayList<>();
6285183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal        for (ComponentKey key : mSearchResults) {
6295183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal            AppInfo match = mComponentToAppMap.get(key);
6305183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal            if (match != null) {
6315183285847816cee9d0db6a8a7ab1a5929163e4eSunny Goyal                result.add(match);
6325683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal            }
6335683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        }
634853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler
635853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler        // adding recently used instant apps
636853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler        if (mDiscoveredApps.size() > 0) {
637853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler            for (int i = 0; i < mDiscoveredApps.size(); i++) {
638853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                AppDiscoveryAppInfo discoveryAppInfo = mDiscoveredApps.get(i);
639853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                if (discoveryAppInfo.isRecent) {
640853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                    result.add(discoveryAppInfo);
641853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler                }
642853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler            }
643853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler            Collections.sort(result, mAppNameComparator);
644853c13d427c638899cd0205aa01bcce7ae4a1e41Mario Bertschler        }
6455683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal        return result;
6465683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal    }
6475683f871722254e4e357cf3fb77cd28156278e51Sunny Goyal
6488ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler    public AppInfo findApp(ComponentKeyMapper<AppInfo> mapper) {
6498ff9e1d6790d64eb5f8ad9e9721e607978b50583Mario Bertschler        return mapper.getItem(mComponentToAppMap);
650d36ed7d982aaa8f682df408548bb5aadb666a066Sunny Goyal    }
651d36ed7d982aaa8f682df408548bb5aadb666a066Sunny Goyal
652208ed75cfdb02e571273d73d056d8ed7f6f756ebWinson Chung    /**
6533abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung     * Returns the cached section name for the given title, recomputing and updating the cache if
6543abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung     * the title has no cached section name.
6553abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung     */
6563abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    private String getAndUpdateCachedSectionName(CharSequence title) {
6573abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        String sectionName = mCachedSectionNames.get(title);
6583abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        if (sectionName == null) {
6593abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            sectionName = mIndexer.computeSectionName(title);
6603abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung            mCachedSectionNames.put(title, sectionName);
6613abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        }
6623abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung        return sectionName;
6633abcd5ba1ba0fe4d8061309dd073e36c64b05963Winson Chung    }
6640fc6f684e730b0137900fe317f2c759c1b3909c7Mario Bertschler
66593f98eaf1800024cb2f28379bdd997f3debae63aWinson Chung}
666