1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.intelligence.search.query; 18 19 import static com.android.settings.intelligence.search.sitemap.HighlightableMenu.MENU_KEY_APPS; 20 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.ModuleInfo; 25 import android.content.pm.PackageManager; 26 import android.net.Uri; 27 import android.provider.Settings; 28 29 import com.android.settings.intelligence.R; 30 import com.android.settings.intelligence.nano.SettingsIntelligenceLogProto; 31 import com.android.settings.intelligence.search.AppSearchResult; 32 import com.android.settings.intelligence.search.ResultPayload; 33 import com.android.settings.intelligence.search.SearchResult; 34 import com.android.settings.intelligence.search.indexing.DatabaseIndexingUtils; 35 import com.android.settings.intelligence.search.sitemap.HighlightableMenu; 36 import com.android.settings.intelligence.search.sitemap.SiteMapManager; 37 38 import java.util.ArrayList; 39 import java.util.Collections; 40 import java.util.List; 41 42 /** 43 * Search loader for installed apps. 44 */ 45 public class InstalledAppResultTask extends SearchQueryTask.QueryWorker { 46 47 private static final int QUERY_WORKER_ID = 48 SettingsIntelligenceLogProto.SettingsIntelligenceEvent.SEARCH_QUERY_INSTALLED_APPS; 49 private static final String INTENT_SCHEME = "package"; 50 51 private final PackageManager mPackageManager; 52 private List<String> mBreadcrumb; 53 newTask(Context context, SiteMapManager siteMapManager, String query)54 public static SearchQueryTask newTask(Context context, SiteMapManager siteMapManager, 55 String query) { 56 return new SearchQueryTask(new InstalledAppResultTask(context, siteMapManager, query)); 57 } 58 InstalledAppResultTask(Context context, SiteMapManager siteMapManager, String query)59 public InstalledAppResultTask(Context context, SiteMapManager siteMapManager, 60 String query) { 61 super(context, siteMapManager, query); 62 mPackageManager = context.getPackageManager(); 63 } 64 65 @Override getQueryWorkerId()66 protected int getQueryWorkerId() { 67 return QUERY_WORKER_ID; 68 } 69 70 @Override query()71 protected List<? extends SearchResult> query() { 72 final List<AppSearchResult> results = new ArrayList<>(); 73 74 List<ApplicationInfo> appsInfo = mPackageManager.getInstalledApplications( 75 PackageManager.MATCH_DISABLED_COMPONENTS 76 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS 77 | PackageManager.MATCH_INSTANT); 78 79 for (ApplicationInfo info : appsInfo) { 80 if (!info.enabled 81 && mPackageManager.getApplicationEnabledSetting(info.packageName) 82 != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) { 83 // Disabled by something other than user, skip. 84 continue; 85 } 86 try { 87 ModuleInfo moduleInfo = mPackageManager.getModuleInfo(info.packageName, 0); 88 if(moduleInfo.isHidden()) { 89 // The app is hidden, skip 90 continue; 91 } 92 } catch (PackageManager.NameNotFoundException e) { 93 // this should not happen here 94 continue; 95 } 96 97 final CharSequence label = info.loadLabel(mPackageManager); 98 final int wordDiff = SearchQueryUtils.getWordDifference(label.toString(), mQuery); 99 if (wordDiff == SearchQueryUtils.NAME_NO_MATCH) { 100 continue; 101 } 102 103 final Intent targetIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) 104 .setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) 105 .setData(Uri.fromParts(INTENT_SCHEME, info.packageName, null /* fragment */)) 106 .putExtra(DatabaseIndexingUtils.EXTRA_SOURCE_METRICS_CATEGORY, 107 DatabaseIndexingUtils.DASHBOARD_SEARCH_RESULTS); 108 final Intent intent = HighlightableMenu.isFeatureEnabled(mContext) 109 ? DatabaseIndexingUtils.buildSearchTrampolineIntent(targetIntent, MENU_KEY_APPS) 110 : targetIntent; 111 112 final AppSearchResult.Builder builder = new AppSearchResult.Builder(); 113 builder.setAppInfo(info) 114 .setDataKey(info.packageName) 115 .setTitle(info.loadLabel(mPackageManager)) 116 .setRank(getRank(wordDiff)) 117 .addBreadcrumbs(getBreadCrumb()) 118 .setPayload(new ResultPayload(intent)); 119 results.add(builder.build()); 120 } 121 122 Collections.sort(results); 123 return results; 124 } 125 getBreadCrumb()126 private List<String> getBreadCrumb() { 127 if (mBreadcrumb == null || mBreadcrumb.isEmpty()) { 128 mBreadcrumb = mSiteMapManager.buildBreadCrumb( 129 mContext, "com.android.settings.applications.ManageApplications", 130 mContext.getString(R.string.applications_settings)); 131 } 132 return mBreadcrumb; 133 } 134 135 /** 136 * A temporary ranking scheme for installed apps. 137 * 138 * @param wordDiff difference between query length and app name length. 139 * @return the ranking. 140 */ getRank(int wordDiff)141 private int getRank(int wordDiff) { 142 if (wordDiff < 6) { 143 return 2; 144 } 145 return 3; 146 } 147 } 148 149