• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.launcher3;
18 
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.ActivityInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ResolveInfo;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 
30 /**
31  * Stores the list of all applications for the all apps view.
32  */
33 class AllAppsList {
34     public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
35 
36     /** The list off all apps. */
37     public ArrayList<AppInfo> data =
38             new ArrayList<AppInfo>(DEFAULT_APPLICATIONS_NUMBER);
39     /** The list of apps that have been added since the last notify() call. */
40     public ArrayList<AppInfo> added =
41             new ArrayList<AppInfo>(DEFAULT_APPLICATIONS_NUMBER);
42     /** The list of apps that have been removed since the last notify() call. */
43     public ArrayList<AppInfo> removed = new ArrayList<AppInfo>();
44     /** The list of apps that have been modified since the last notify() call. */
45     public ArrayList<AppInfo> modified = new ArrayList<AppInfo>();
46 
47     private IconCache mIconCache;
48 
49     private AppFilter mAppFilter;
50 
51     /**
52      * Boring constructor.
53      */
AllAppsList(IconCache iconCache, AppFilter appFilter)54     public AllAppsList(IconCache iconCache, AppFilter appFilter) {
55         mIconCache = iconCache;
56         mAppFilter = appFilter;
57     }
58 
59     /**
60      * Add the supplied ApplicationInfo objects to the list, and enqueue it into the
61      * list to broadcast when notify() is called.
62      *
63      * If the app is already in the list, doesn't add it.
64      */
add(AppInfo info)65     public void add(AppInfo info) {
66         if (mAppFilter != null && !mAppFilter.shouldShowApp(info.componentName)) {
67             return;
68         }
69         if (findActivity(data, info.componentName)) {
70             return;
71         }
72         data.add(info);
73         added.add(info);
74     }
75 
clear()76     public void clear() {
77         data.clear();
78         // TODO: do we clear these too?
79         added.clear();
80         removed.clear();
81         modified.clear();
82     }
83 
size()84     public int size() {
85         return data.size();
86     }
87 
get(int index)88     public AppInfo get(int index) {
89         return data.get(index);
90     }
91 
92     /**
93      * Add the icons for the supplied apk called packageName.
94      */
addPackage(Context context, String packageName)95     public void addPackage(Context context, String packageName) {
96         final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
97 
98         if (matches.size() > 0) {
99             for (ResolveInfo info : matches) {
100                 add(new AppInfo(context.getPackageManager(), info, mIconCache, null));
101             }
102         }
103     }
104 
105     /**
106      * Remove the apps for the given apk identified by packageName.
107      */
removePackage(String packageName)108     public void removePackage(String packageName) {
109         final List<AppInfo> data = this.data;
110         for (int i = data.size() - 1; i >= 0; i--) {
111             AppInfo info = data.get(i);
112             final ComponentName component = info.intent.getComponent();
113             if (packageName.equals(component.getPackageName())) {
114                 removed.add(info);
115                 data.remove(i);
116             }
117         }
118         mIconCache.remove(packageName);
119     }
120 
121     /**
122      * Add and remove icons for this package which has been updated.
123      */
updatePackage(Context context, String packageName)124     public void updatePackage(Context context, String packageName) {
125         final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
126         if (matches.size() > 0) {
127             // Find disabled/removed activities and remove them from data and add them
128             // to the removed list.
129             for (int i = data.size() - 1; i >= 0; i--) {
130                 final AppInfo applicationInfo = data.get(i);
131                 final ComponentName component = applicationInfo.intent.getComponent();
132                 if (packageName.equals(component.getPackageName())) {
133                     if (!findActivity(matches, component)) {
134                         removed.add(applicationInfo);
135                         mIconCache.remove(component);
136                         data.remove(i);
137                     }
138                 }
139             }
140 
141             // Find enabled activities and add them to the adapter
142             // Also updates existing activities with new labels/icons
143             int count = matches.size();
144             for (int i = 0; i < count; i++) {
145                 final ResolveInfo info = matches.get(i);
146                 AppInfo applicationInfo = findApplicationInfoLocked(
147                         info.activityInfo.applicationInfo.packageName,
148                         info.activityInfo.name);
149                 if (applicationInfo == null) {
150                     add(new AppInfo(context.getPackageManager(), info, mIconCache, null));
151                 } else {
152                     mIconCache.remove(applicationInfo.componentName);
153                     mIconCache.getTitleAndIcon(applicationInfo, info, null);
154                     modified.add(applicationInfo);
155                 }
156             }
157         } else {
158             // Remove all data for this package.
159             for (int i = data.size() - 1; i >= 0; i--) {
160                 final AppInfo applicationInfo = data.get(i);
161                 final ComponentName component = applicationInfo.intent.getComponent();
162                 if (packageName.equals(component.getPackageName())) {
163                     removed.add(applicationInfo);
164                     mIconCache.remove(component);
165                     data.remove(i);
166                 }
167             }
168         }
169     }
170 
171     /**
172      * Query the package manager for MAIN/LAUNCHER activities in the supplied package.
173      */
findActivitiesForPackage(Context context, String packageName)174     static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
175         final PackageManager packageManager = context.getPackageManager();
176 
177         final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
178         mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
179         mainIntent.setPackage(packageName);
180 
181         final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
182         return apps != null ? apps : new ArrayList<ResolveInfo>();
183     }
184 
185     /**
186      * Returns whether <em>apps</em> contains <em>component</em>.
187      */
findActivity(List<ResolveInfo> apps, ComponentName component)188     private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
189         final String className = component.getClassName();
190         for (ResolveInfo info : apps) {
191             final ActivityInfo activityInfo = info.activityInfo;
192             if (activityInfo.name.equals(className)) {
193                 return true;
194             }
195         }
196         return false;
197     }
198 
199     /**
200      * Returns whether <em>apps</em> contains <em>component</em>.
201      */
findActivity(ArrayList<AppInfo> apps, ComponentName component)202     private static boolean findActivity(ArrayList<AppInfo> apps, ComponentName component) {
203         final int N = apps.size();
204         for (int i=0; i<N; i++) {
205             final AppInfo info = apps.get(i);
206             if (info.componentName.equals(component)) {
207                 return true;
208             }
209         }
210         return false;
211     }
212 
213     /**
214      * Find an ApplicationInfo object for the given packageName and className.
215      */
findApplicationInfoLocked(String packageName, String className)216     private AppInfo findApplicationInfoLocked(String packageName, String className) {
217         for (AppInfo info: data) {
218             final ComponentName component = info.intent.getComponent();
219             if (packageName.equals(component.getPackageName())
220                     && className.equals(component.getClassName())) {
221                 return info;
222             }
223         }
224         return null;
225     }
226 }
227