136d0d143be78e234e7c92897cb63458279d6549bFan Zhang/* 22078bc2358031ef3a191900d9036daf4251911c1Matthew Fritze * Copyright (C) 2017 The Android Open Source Project 336d0d143be78e234e7c92897cb63458279d6549bFan Zhang * 436d0d143be78e234e7c92897cb63458279d6549bFan Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 536d0d143be78e234e7c92897cb63458279d6549bFan Zhang * you may not use this file except in compliance with the License. 636d0d143be78e234e7c92897cb63458279d6549bFan Zhang * You may obtain a copy of the License at 736d0d143be78e234e7c92897cb63458279d6549bFan Zhang * 836d0d143be78e234e7c92897cb63458279d6549bFan Zhang * http://www.apache.org/licenses/LICENSE-2.0 936d0d143be78e234e7c92897cb63458279d6549bFan Zhang * 1036d0d143be78e234e7c92897cb63458279d6549bFan Zhang * Unless required by applicable law or agreed to in writing, software 1136d0d143be78e234e7c92897cb63458279d6549bFan Zhang * distributed under the License is distributed on an "AS IS" BASIS, 1236d0d143be78e234e7c92897cb63458279d6549bFan Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1336d0d143be78e234e7c92897cb63458279d6549bFan Zhang * See the License for the specific language governing permissions and 1436d0d143be78e234e7c92897cb63458279d6549bFan Zhang * limitations under the License. 152078bc2358031ef3a191900d9036daf4251911c1Matthew Fritze * 1636d0d143be78e234e7c92897cb63458279d6549bFan Zhang */ 1736d0d143be78e234e7c92897cb63458279d6549bFan Zhang 182078bc2358031ef3a191900d9036daf4251911c1Matthew Fritzepackage com.android.settings.search; 1936d0d143be78e234e7c92897cb63458279d6549bFan Zhang 2036d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.content.Context; 2136d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.content.Intent; 2236d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.content.pm.ApplicationInfo; 2336d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.content.pm.PackageManager; 24ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhangimport android.content.pm.ResolveInfo; 2536d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.content.pm.UserInfo; 2636d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.net.Uri; 2736d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.os.UserHandle; 2836d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.os.UserManager; 2936d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.provider.Settings; 30fbcf4e6e14d090aaced06d3f8708d6e9df1962baFan Zhangimport android.support.annotation.VisibleForTesting; 3136d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport android.text.TextUtils; 3236d0d143be78e234e7c92897cb63458279d6549bFan Zhang 338fc4e819a272d80bd2e8f2ed305a165154c46783Fan Zhangimport com.android.internal.logging.nano.MetricsProto; 34248d95c61809b253eb16fb1d597ed5e2f83ada78Fan Zhangimport com.android.settings.R; 358fc4e819a272d80bd2e8f2ed305a165154c46783Fan Zhangimport com.android.settings.SettingsActivity; 36a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhangimport com.android.settings.applications.ManageApplications; 3736d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport com.android.settings.applications.PackageManagerWrapper; 38a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhangimport com.android.settings.dashboard.SiteMapManager; 3936d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport com.android.settings.utils.AsyncLoader; 4036d0d143be78e234e7c92897cb63458279d6549bFan Zhang 410d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhangimport java.util.ArrayList; 42683ccdf97bd8b3ed30b7014f2df17227cff92561Soroosh Mariooryadimport java.util.HashSet; 4336d0d143be78e234e7c92897cb63458279d6549bFan Zhangimport java.util.List; 449f3f5f4fed23eac98cf7441c025fd6100e020ed2Tony Makimport java.util.Objects; 45683ccdf97bd8b3ed30b7014f2df17227cff92561Soroosh Mariooryadimport java.util.Set; 4636d0d143be78e234e7c92897cb63458279d6549bFan Zhang 4736d0d143be78e234e7c92897cb63458279d6549bFan Zhang/** 4836d0d143be78e234e7c92897cb63458279d6549bFan Zhang * Search loader for installed apps. 4936d0d143be78e234e7c92897cb63458279d6549bFan Zhang */ 50683ccdf97bd8b3ed30b7014f2df17227cff92561Soroosh Mariooryadpublic class InstalledAppResultLoader extends AsyncLoader<Set<? extends SearchResult>> { 5136d0d143be78e234e7c92897cb63458279d6549bFan Zhang 5236d0d143be78e234e7c92897cb63458279d6549bFan Zhang private static final int NAME_NO_MATCH = -1; 53ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang private static final Intent LAUNCHER_PROBE = new Intent(Intent.ACTION_MAIN) 54ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang .addCategory(Intent.CATEGORY_LAUNCHER); 5536d0d143be78e234e7c92897cb63458279d6549bFan Zhang 56a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang private List<String> mBreadcrumb; 57a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang private SiteMapManager mSiteMapManager; 58fbcf4e6e14d090aaced06d3f8708d6e9df1962baFan Zhang @VisibleForTesting 59fbcf4e6e14d090aaced06d3f8708d6e9df1962baFan Zhang final String mQuery; 6036d0d143be78e234e7c92897cb63458279d6549bFan Zhang private final UserManager mUserManager; 6136d0d143be78e234e7c92897cb63458279d6549bFan Zhang private final PackageManagerWrapper mPackageManager; 620d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang private final List<ResolveInfo> mHomeActivities = new ArrayList<>(); 63ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang 6436d0d143be78e234e7c92897cb63458279d6549bFan Zhang public InstalledAppResultLoader(Context context, PackageManagerWrapper pmWrapper, 6540ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze String query, SiteMapManager mapManager) { 6636d0d143be78e234e7c92897cb63458279d6549bFan Zhang super(context); 6740ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze mSiteMapManager = mapManager; 6836d0d143be78e234e7c92897cb63458279d6549bFan Zhang mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 6936d0d143be78e234e7c92897cb63458279d6549bFan Zhang mPackageManager = pmWrapper; 7036d0d143be78e234e7c92897cb63458279d6549bFan Zhang mQuery = query; 7136d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 7236d0d143be78e234e7c92897cb63458279d6549bFan Zhang 7336d0d143be78e234e7c92897cb63458279d6549bFan Zhang @Override 74683ccdf97bd8b3ed30b7014f2df17227cff92561Soroosh Mariooryad public Set<? extends SearchResult> loadInBackground() { 75683ccdf97bd8b3ed30b7014f2df17227cff92561Soroosh Mariooryad final Set<AppSearchResult> results = new HashSet<>(); 7636d0d143be78e234e7c92897cb63458279d6549bFan Zhang final PackageManager pm = mPackageManager.getPackageManager(); 7736d0d143be78e234e7c92897cb63458279d6549bFan Zhang 780d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang mHomeActivities.clear(); 790d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang mPackageManager.getHomeActivities(mHomeActivities); 800d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang 8136d0d143be78e234e7c92897cb63458279d6549bFan Zhang for (UserInfo user : getUsersToCount()) { 8236d0d143be78e234e7c92897cb63458279d6549bFan Zhang final List<ApplicationInfo> apps = 8336d0d143be78e234e7c92897cb63458279d6549bFan Zhang mPackageManager.getInstalledApplicationsAsUser( 8436d0d143be78e234e7c92897cb63458279d6549bFan Zhang PackageManager.MATCH_DISABLED_COMPONENTS 8536d0d143be78e234e7c92897cb63458279d6549bFan Zhang | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 8636d0d143be78e234e7c92897cb63458279d6549bFan Zhang | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0), 8736d0d143be78e234e7c92897cb63458279d6549bFan Zhang user.id); 8836d0d143be78e234e7c92897cb63458279d6549bFan Zhang for (ApplicationInfo info : apps) { 89ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang if (!shouldIncludeAsCandidate(info, user)) { 9036d0d143be78e234e7c92897cb63458279d6549bFan Zhang continue; 9136d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 9236d0d143be78e234e7c92897cb63458279d6549bFan Zhang final CharSequence label = info.loadLabel(pm); 9336d0d143be78e234e7c92897cb63458279d6549bFan Zhang final int wordDiff = getWordDifference(label.toString(), mQuery); 9436d0d143be78e234e7c92897cb63458279d6549bFan Zhang if (wordDiff == NAME_NO_MATCH) { 9536d0d143be78e234e7c92897cb63458279d6549bFan Zhang continue; 9636d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 9736d0d143be78e234e7c92897cb63458279d6549bFan Zhang final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) 9836d0d143be78e234e7c92897cb63458279d6549bFan Zhang .setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) 998fc4e819a272d80bd2e8f2ed305a165154c46783Fan Zhang .setData(Uri.fromParts("package", info.packageName, null)) 1008fc4e819a272d80bd2e8f2ed305a165154c46783Fan Zhang .putExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY, 1018fc4e819a272d80bd2e8f2ed305a165154c46783Fan Zhang MetricsProto.MetricsEvent.DASHBOARD_SEARCH_RESULTS); 10236d0d143be78e234e7c92897cb63458279d6549bFan Zhang 10340ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze final AppSearchResult.Builder builder = new AppSearchResult.Builder(); 10440ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze builder.setAppInfo(info) 1059f3f5f4fed23eac98cf7441c025fd6100e020ed2Tony Mak .setStableId(Objects.hash(info.packageName, user.id)) 1066efea1e624bb4b48290000cfdb82df224a31b81dMatthew Fritze .setTitle(info.loadLabel(pm)) 1076efea1e624bb4b48290000cfdb82df224a31b81dMatthew Fritze .setRank(getRank(wordDiff)) 108a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang .addBreadcrumbs(getBreadCrumb()) 1096efea1e624bb4b48290000cfdb82df224a31b81dMatthew Fritze .setPayload(new ResultPayload(intent)); 11036d0d143be78e234e7c92897cb63458279d6549bFan Zhang results.add(builder.build()); 11136d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 11236d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 11336d0d143be78e234e7c92897cb63458279d6549bFan Zhang return results; 11436d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 11536d0d143be78e234e7c92897cb63458279d6549bFan Zhang 1160d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang /** 1170d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang * Returns true if the candidate should be included in candidate list 1180d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang * <p/> 1190d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang * This method matches logic in {@code ApplicationState#FILTER_DOWNLOADED_AND_LAUNCHER}. 1200d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang */ 121ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang private boolean shouldIncludeAsCandidate(ApplicationInfo info, UserInfo user) { 1220d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang // Not system app 123ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 124ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang || (info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 125ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang return true; 126ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang } 1270d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang // Shows up in launcher 128ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang final Intent launchIntent = new Intent(LAUNCHER_PROBE) 129ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang .setPackage(info.packageName); 130ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang final List<ResolveInfo> intents = mPackageManager.queryIntentActivitiesAsUser( 131ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang launchIntent, 132ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang PackageManager.MATCH_DISABLED_COMPONENTS 133ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang | PackageManager.MATCH_DIRECT_BOOT_AWARE 134ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 135ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang user.id); 1360d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang if (intents != null && intents.size() != 0) { 1370d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang return true; 1380d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang } 1390d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang // Is launcher app itself 1400d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang return isPackageInList(mHomeActivities, info.packageName); 141ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang } 142ba83109807f07371a2e3a2dcebd34b6f9985c345Fan Zhang 14336d0d143be78e234e7c92897cb63458279d6549bFan Zhang @Override 144683ccdf97bd8b3ed30b7014f2df17227cff92561Soroosh Mariooryad protected void onDiscardResult(Set<? extends SearchResult> result) { 14536d0d143be78e234e7c92897cb63458279d6549bFan Zhang 14636d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 14736d0d143be78e234e7c92897cb63458279d6549bFan Zhang 14836d0d143be78e234e7c92897cb63458279d6549bFan Zhang private List<UserInfo> getUsersToCount() { 14936d0d143be78e234e7c92897cb63458279d6549bFan Zhang return mUserManager.getProfiles(UserHandle.myUserId()); 15036d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 15136d0d143be78e234e7c92897cb63458279d6549bFan Zhang 15236d0d143be78e234e7c92897cb63458279d6549bFan Zhang /** 15336d0d143be78e234e7c92897cb63458279d6549bFan Zhang * Returns "difference" between appName and query string. appName must contain all 15443f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * characters from query as a prefix to a word, in the same order. 15543f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * If not, returns NAME_NO_MATCH. 15643f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * If they do match, returns an int value representing how different they are, 15743f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * and larger values means they are less similar. 15836d0d143be78e234e7c92897cb63458279d6549bFan Zhang * <p/> 15936d0d143be78e234e7c92897cb63458279d6549bFan Zhang * Example: 16043f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * appName: Abcde, query: Abcde, Returns 0 16143f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * appName: Abcde, query: abc, Returns 2 16243f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * appName: Abcde, query: ab, Returns 3 16343f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * appName: Abcde, query: bc, Returns NAME_NO_MATCH 16436d0d143be78e234e7c92897cb63458279d6549bFan Zhang * appName: Abcde, query: xyz, Returns NAME_NO_MATCH 16543f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze * appName: Abc de, query: de, Returns 4 1665035f8c5590a8eea7bf372a325a4aa0ee1e96149Fan Zhang * TODO: Move this to a common util class. 16736d0d143be78e234e7c92897cb63458279d6549bFan Zhang */ 1685035f8c5590a8eea7bf372a325a4aa0ee1e96149Fan Zhang static int getWordDifference(String appName, String query) { 16936d0d143be78e234e7c92897cb63458279d6549bFan Zhang if (TextUtils.isEmpty(appName) || TextUtils.isEmpty(query)) { 17036d0d143be78e234e7c92897cb63458279d6549bFan Zhang return NAME_NO_MATCH; 17136d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 17243f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 17343f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze final char[] queryTokens = query.toLowerCase().toCharArray(); 17443f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze final char[] appTokens = appName.toLowerCase().toCharArray(); 17543f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze final int appLength = appTokens.length; 17643f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze if (queryTokens.length > appLength) { 17736d0d143be78e234e7c92897cb63458279d6549bFan Zhang return NAME_NO_MATCH; 17836d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 17943f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 18036d0d143be78e234e7c92897cb63458279d6549bFan Zhang int i = 0; 18143f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze int j; 18243f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 18343f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze while (i < appLength) { 18443f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze j = 0; 18543f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Currently matching a prefix 18643f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze while ((i + j < appLength) && (queryTokens[j] == appTokens[i + j])) { 18743f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Matched the entire query 18843f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze if (++j >= queryTokens.length) { 18943f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Use the diff in length as a proxy of how close the 2 words match. 19043f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Value range from 0 to infinity. 19143f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze return appLength - queryTokens.length; 19243f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze } 19343f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze } 19443f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 19543f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze i += j; 19643f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 19743f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Remaining string is longer that the query or we have search the whole app name. 19843f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze if (queryTokens.length > appLength - i) { 19943f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze return NAME_NO_MATCH; 20043f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze } 20143f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 20243f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // This is the first index where app name and query name are different 20343f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Find the next space in the app name or the end of the app name. 20443f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze while ((i < appLength) && (!Character.isWhitespace(appTokens[i++]))) ; 20543f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze 20643f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Find the start of the next word 20743f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze while ((i < appLength) && !(Character.isLetter(appTokens[i]) 20843f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze || Character.isDigit(appTokens[i]))) { 20943f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze // Increment in body because we cannot guarantee which condition was true 21043f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze i++; 21136d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 21236d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 21343f7fb1b8f061fbf803a2557da1464263445437cMatthew Fritze return NAME_NO_MATCH; 21436d0d143be78e234e7c92897cb63458279d6549bFan Zhang } 215a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang 2160d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang private boolean isPackageInList(List<ResolveInfo> resolveInfos, String pkg) { 2170d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang for (ResolveInfo info : resolveInfos) { 2180d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang if (TextUtils.equals(info.activityInfo.packageName, pkg)) { 2190d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang return true; 2200d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang } 2210d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang } 2220d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang return false; 2230d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang } 2240d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang 225a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang private List<String> getBreadCrumb() { 226a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang if (mBreadcrumb == null || mBreadcrumb.isEmpty()) { 227a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang final Context context = getContext(); 228a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang mBreadcrumb = mSiteMapManager.buildBreadCrumb( 229a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang context, ManageApplications.class.getName(), 230a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang context.getString(R.string.applications_settings)); 231a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang } 232a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang return mBreadcrumb; 233a96b11f65d9f29dd4037da85e12f5cf9dcfa0176Fan Zhang } 23440ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze 23540ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze /** 23640ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze * A temporary ranking scheme for installed apps. 2370d8e1f23cbec501eab0f6fc8a287c60aad3c750eFan Zhang * 23840ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze * @param wordDiff difference between query length and app name length. 23940ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze * @return the ranking. 24040ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze */ 24140ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze private int getRank(int wordDiff) { 24240ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze if (wordDiff < 6) { 243b7b286cb893268bec38584acdf5696f68675ecedMatthew Fritze return 2; 24440ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze } 245b7b286cb893268bec38584acdf5696f68675ecedMatthew Fritze return 3; 24640ce0fab758714c973945ec8f053c52076d5fc50Matthew Fritze } 24736d0d143be78e234e7c92897cb63458279d6549bFan Zhang} 248