1 /*
2  * Copyright (C) 2016 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.display;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.pm.ResolveInfo;
23 import android.graphics.drawable.Drawable;
24 import android.os.UserHandle;
25 import android.util.AttributeSet;
26 import android.util.IconDrawableFactory;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.widget.ArrayAdapter;
30 import android.widget.GridView;
31 import android.widget.ImageView;
32 
33 import androidx.annotation.VisibleForTesting;
34 
35 import com.android.settings.R;
36 
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.List;
40 
41 public class AppGridView extends GridView {
AppGridView(Context context)42     public AppGridView(Context context) {
43         super(context);
44         init(context);
45     }
46 
AppGridView(Context context, AttributeSet attrs)47     public AppGridView(Context context, AttributeSet attrs) {
48         super(context, attrs);
49         init(context);
50     }
51 
AppGridView(Context context, AttributeSet attrs, int defStyleAttr)52     public AppGridView(Context context, AttributeSet attrs, int defStyleAttr) {
53         super(context, attrs, defStyleAttr);
54         init(context);
55     }
56 
AppGridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleResId)57     public AppGridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleResId) {
58         super(context, attrs, defStyleAttr, defStyleResId);
59 
60         init(context);
61 
62     }
63 
init(Context context)64     private void init(Context context) {
65         setAdapter(new AppsAdapter(context, R.layout.screen_zoom_preview_app_icon,
66                 android.R.id.text1, android.R.id.icon1));
67     }
68 
69     /**
70      * Loads application labels and icons.
71      */
72     @VisibleForTesting
73     public static class AppsAdapter extends ArrayAdapter<ActivityEntry> {
74         private final PackageManager mPackageManager;
75         private final int mIconResId;
76 
AppsAdapter(Context context, int layout, int textResId, int iconResId)77         public AppsAdapter(Context context, int layout, int textResId, int iconResId) {
78             super(context, layout, textResId);
79 
80             mIconResId = iconResId;
81             mPackageManager = context.getPackageManager();
82 
83             loadAllApps();
84         }
85 
86         @Override
getView(int position, View convertView, ViewGroup parent)87         public View getView(int position, View convertView, ViewGroup parent) {
88             final View view = super.getView(position, convertView, parent);
89             final ActivityEntry entry = getItem(position);
90             final ImageView iconView = view.findViewById(mIconResId);
91             iconView.setImageDrawable(entry.getIcon());
92             return view;
93         }
94 
95         @Override
hasStableIds()96         public boolean hasStableIds() {
97             return true;
98         }
99 
100         @Override
getItemId(int position)101         public long getItemId(int position) {
102             return position;
103         }
104 
105         @Override
isEnabled(int position)106         public boolean isEnabled(int position) {
107             return false;
108         }
109 
loadAllApps()110         private void loadAllApps() {
111             final int needAppCount = 6;
112             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
113             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
114 
115             final PackageManager pm = mPackageManager;
116             final ArrayList<ActivityEntry> results = new ArrayList<>();
117             final List<ResolveInfo> infos = pm.queryIntentActivities(mainIntent, 0);
118             final IconDrawableFactory iconFactory = IconDrawableFactory.newInstance(getContext());
119             for (ResolveInfo info : infos) {
120                 final CharSequence label = info.loadLabel(pm);
121                 if (label != null) {
122                     results.add(new ActivityEntry(info, label.toString(), iconFactory));
123                 }
124                 if (results.size() >= needAppCount) {
125                     break;
126                 }
127             }
128 
129             Collections.sort(results);
130 
131             addAll(results);
132         }
133     }
134 
135     /**
136      * Class used for caching the activity label and icon.
137      */
138     @VisibleForTesting
139     public static class ActivityEntry implements Comparable<ActivityEntry> {
140 
141         public final ResolveInfo info;
142         public final String label;
143         private final IconDrawableFactory mIconFactory;
144         private final int mUserId;
145 
ActivityEntry(ResolveInfo info, String label, IconDrawableFactory iconFactory)146         public ActivityEntry(ResolveInfo info, String label, IconDrawableFactory iconFactory) {
147             this.info = info;
148             this.label = label;
149             mIconFactory = iconFactory;
150             mUserId = UserHandle.myUserId();
151         }
152 
153         @Override
compareTo(ActivityEntry entry)154         public int compareTo(ActivityEntry entry) {
155             return label.compareToIgnoreCase(entry.label);
156         }
157 
158         @Override
toString()159         public String toString() {
160             return label;
161         }
162 
getIcon()163         public Drawable getIcon() {
164             return mIconFactory.getBadgedIcon(
165                     info.activityInfo, info.activityInfo.applicationInfo, mUserId);
166         }
167     }
168 }
169