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 android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.ApplicationInfo;
22 import android.content.pm.PackageManager;
23 import android.net.Uri;
24 import android.provider.Settings;
25 
26 import com.android.settings.intelligence.R;
27 import com.android.settings.intelligence.nano.SettingsIntelligenceLogProto;
28 import com.android.settings.intelligence.search.AppSearchResult;
29 import com.android.settings.intelligence.search.ResultPayload;
30 import com.android.settings.intelligence.search.SearchResult;
31 import com.android.settings.intelligence.search.indexing.DatabaseIndexingUtils;
32 import com.android.settings.intelligence.search.sitemap.SiteMapManager;
33 
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.List;
37 
38 /**
39  * Search loader for installed apps.
40  */
41 public class InstalledAppResultTask extends SearchQueryTask.QueryWorker {
42 
43     public static final int QUERY_WORKER_ID =
44             SettingsIntelligenceLogProto.SettingsIntelligenceEvent.SEARCH_QUERY_INSTALLED_APPS;
45 
46     private final PackageManager mPackageManager;
47     private final String INTENT_SCHEME = "package";
48     private List<String> mBreadcrumb;
49 
newTask(Context context, SiteMapManager siteMapManager, String query)50     public static SearchQueryTask newTask(Context context, SiteMapManager siteMapManager,
51             String query) {
52         return new SearchQueryTask(new InstalledAppResultTask(context, siteMapManager, query));
53     }
54 
InstalledAppResultTask(Context context, SiteMapManager siteMapManager, String query)55     public InstalledAppResultTask(Context context, SiteMapManager siteMapManager,
56             String query) {
57         super(context, siteMapManager, query);
58         mPackageManager = context.getPackageManager();
59     }
60 
61     @Override
getQueryWorkerId()62     protected int getQueryWorkerId() {
63         return QUERY_WORKER_ID;
64     }
65 
66     @Override
query()67     protected List<? extends SearchResult> query() {
68         final List<AppSearchResult> results = new ArrayList<>();
69 
70         List<ApplicationInfo> appsInfo = mPackageManager.getInstalledApplications(
71                 PackageManager.MATCH_DISABLED_COMPONENTS
72                         | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
73                         | PackageManager.MATCH_INSTANT);
74 
75         for (ApplicationInfo info : appsInfo) {
76             if (!info.enabled
77                     && mPackageManager.getApplicationEnabledSetting(info.packageName)
78                     != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
79                 // Disabled by something other than user, skip.
80                 continue;
81             }
82             final CharSequence label = info.loadLabel(mPackageManager);
83             final int wordDiff = SearchQueryUtils.getWordDifference(label.toString(), mQuery);
84             if (wordDiff == SearchQueryUtils.NAME_NO_MATCH) {
85                 continue;
86             }
87 
88             final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
89                     .setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
90                     .setData(
91                             Uri.fromParts(INTENT_SCHEME, info.packageName, null /* fragment */))
92                     .putExtra(DatabaseIndexingUtils.EXTRA_SOURCE_METRICS_CATEGORY,
93                             DatabaseIndexingUtils.DASHBOARD_SEARCH_RESULTS);
94 
95             final AppSearchResult.Builder builder = new AppSearchResult.Builder();
96             builder.setAppInfo(info)
97                     .setDataKey(info.packageName)
98                     .setTitle(info.loadLabel(mPackageManager))
99                     .setRank(getRank(wordDiff))
100                     .addBreadcrumbs(getBreadCrumb())
101                     .setPayload(new ResultPayload(intent));
102             results.add(builder.build());
103         }
104 
105         Collections.sort(results);
106         return results;
107     }
108 
getBreadCrumb()109     private List<String> getBreadCrumb() {
110         if (mBreadcrumb == null || mBreadcrumb.isEmpty()) {
111             mBreadcrumb = mSiteMapManager.buildBreadCrumb(
112                     mContext, "com.android.settings.applications.ManageApplications",
113                     mContext.getString(R.string.applications_settings));
114         }
115         return mBreadcrumb;
116     }
117 
118     /**
119      * A temporary ranking scheme for installed apps.
120      *
121      * @param wordDiff difference between query length and app name length.
122      * @return the ranking.
123      */
getRank(int wordDiff)124     private int getRank(int wordDiff) {
125         if (wordDiff < 6) {
126             return 2;
127         }
128         return 3;
129     }
130 }
131 
132