blob: 4c9bc5eca2b86ef8fb95f70d0b2a88e29fa5e492 [file] [log] [blame]
Joe Onorato9c1289c2009-08-17 11:03:03 -04001/*
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
17package com.android.launcher2;
18
Winson Chungaafa03c2010-06-11 17:34:16 -070019import java.util.ArrayList;
20import java.util.List;
21
Joe Onorato9c1289c2009-08-17 11:03:03 -040022import android.content.ComponentName;
Joe Onorato9c1289c2009-08-17 11:03:03 -040023import android.content.Context;
Winson Chungaafa03c2010-06-11 17:34:16 -070024import android.content.Intent;
Joe Onorato9c1289c2009-08-17 11:03:03 -040025import android.content.pm.ActivityInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
Joe Onorato9c1289c2009-08-17 11:03:03 -040028
Joe Onorato9c1289c2009-08-17 11:03:03 -040029
30/**
31 * Stores the list of all applications for the all apps view.
32 */
33class AllAppsList {
34 public static final int DEFAULT_APPLICATIONS_NUMBER = 42;
35
36 /** The list off all apps. */
Romain Guy5c16f3e2010-01-12 17:24:58 -080037 public ArrayList<ApplicationInfo> data =
38 new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
Joe Onorato9c1289c2009-08-17 11:03:03 -040039 /** The list of apps that have been added since the last notify() call. */
Romain Guy5c16f3e2010-01-12 17:24:58 -080040 public ArrayList<ApplicationInfo> added =
41 new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
Joe Onorato9c1289c2009-08-17 11:03:03 -040042 /** The list of apps that have been removed since the last notify() call. */
Romain Guy5c16f3e2010-01-12 17:24:58 -080043 public ArrayList<ApplicationInfo> removed = new ArrayList<ApplicationInfo>();
Joe Onorato9c1289c2009-08-17 11:03:03 -040044 /** The list of apps that have been modified since the last notify() call. */
Romain Guy5c16f3e2010-01-12 17:24:58 -080045 public ArrayList<ApplicationInfo> modified = new ArrayList<ApplicationInfo>();
Joe Onorato9c1289c2009-08-17 11:03:03 -040046
Joe Onorato0589f0f2010-02-08 13:44:00 -080047 private IconCache mIconCache;
48
Joe Onorato9c1289c2009-08-17 11:03:03 -040049 /**
50 * Boring constructor.
51 */
Joe Onorato0589f0f2010-02-08 13:44:00 -080052 public AllAppsList(IconCache iconCache) {
53 mIconCache = iconCache;
Joe Onorato9c1289c2009-08-17 11:03:03 -040054 }
55
56 /**
57 * Add the supplied ApplicationInfo objects to the list, and enqueue it into the
58 * list to broadcast when notify() is called.
Joe Onoratod65d08e2010-04-20 15:43:37 -040059 *
60 * If the app is already in the list, doesn't add it.
Joe Onorato9c1289c2009-08-17 11:03:03 -040061 */
62 public void add(ApplicationInfo info) {
Joe Onoratod65d08e2010-04-20 15:43:37 -040063 if (findActivity(data, info.componentName)) {
64 return;
65 }
Daniel Sandler054019d2010-04-15 16:28:40 -040066 data.add(info);
67 added.add(info);
Joe Onorato9c1289c2009-08-17 11:03:03 -040068 }
69
70 public void clear() {
71 data.clear();
72 // TODO: do we clear these too?
73 added.clear();
74 removed.clear();
75 modified.clear();
76 }
77
78 public int size() {
79 return data.size();
80 }
81
82 public ApplicationInfo get(int index) {
83 return data.get(index);
84 }
85
86 /**
87 * Add the icons for the supplied apk called packageName.
88 */
89 public void addPackage(Context context, String packageName) {
90 final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
91
92 if (matches.size() > 0) {
Joe Onorato9c1289c2009-08-17 11:03:03 -040093 for (ResolveInfo info : matches) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -070094 add(new ApplicationInfo(context.getPackageManager(), info, mIconCache));
Joe Onorato9c1289c2009-08-17 11:03:03 -040095 }
96 }
97 }
98
99 /**
100 * Remove the apps for the given apk identified by packageName.
101 */
102 public void removePackage(String packageName) {
103 final List<ApplicationInfo> data = this.data;
Romain Guy5c16f3e2010-01-12 17:24:58 -0800104 for (int i = data.size() - 1; i >= 0; i--) {
Joe Onorato9c1289c2009-08-17 11:03:03 -0400105 ApplicationInfo info = data.get(i);
106 final ComponentName component = info.intent.getComponent();
107 if (packageName.equals(component.getPackageName())) {
108 removed.add(info);
109 data.remove(i);
110 }
111 }
112 // This is more aggressive than it needs to be.
Joe Onorato0589f0f2010-02-08 13:44:00 -0800113 mIconCache.flush();
Joe Onorato9c1289c2009-08-17 11:03:03 -0400114 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800115
Joe Onorato9c1289c2009-08-17 11:03:03 -0400116 /**
117 * Add and remove icons for this package which has been updated.
118 */
119 public void updatePackage(Context context, String packageName) {
120 final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
121 if (matches.size() > 0) {
122 // Find disabled/removed activities and remove them from data and add them
123 // to the removed list.
Romain Guy5c16f3e2010-01-12 17:24:58 -0800124 for (int i = data.size() - 1; i >= 0; i--) {
Joe Onorato9c1289c2009-08-17 11:03:03 -0400125 final ApplicationInfo applicationInfo = data.get(i);
126 final ComponentName component = applicationInfo.intent.getComponent();
127 if (packageName.equals(component.getPackageName())) {
128 if (!findActivity(matches, component)) {
129 removed.add(applicationInfo);
Joe Onorato0589f0f2010-02-08 13:44:00 -0800130 mIconCache.remove(component);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400131 data.remove(i);
132 }
133 }
134 }
135
136 // Find enabled activities and add them to the adapter
137 // Also updates existing activities with new labels/icons
Joe Onorato9c1289c2009-08-17 11:03:03 -0400138 int count = matches.size();
Romain Guy5c16f3e2010-01-12 17:24:58 -0800139 for (int i = 0; i < count; i++) {
Joe Onorato9c1289c2009-08-17 11:03:03 -0400140 final ResolveInfo info = matches.get(i);
141 ApplicationInfo applicationInfo = findApplicationInfoLocked(
142 info.activityInfo.applicationInfo.packageName,
143 info.activityInfo.name);
144 if (applicationInfo == null) {
Patrick Dubroy3d605d52010-07-29 13:59:29 -0700145 add(new ApplicationInfo(context.getPackageManager(), info, mIconCache));
Joe Onorato9c1289c2009-08-17 11:03:03 -0400146 } else {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800147 mIconCache.remove(applicationInfo.componentName);
148 mIconCache.getTitleAndIcon(applicationInfo, info);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400149 modified.add(applicationInfo);
150 }
151 }
Dianne Hackborn2d86dfe2010-07-24 16:48:01 -0700152 } else {
153 // Remove all data for this package.
154 for (int i = data.size() - 1; i >= 0; i--) {
155 final ApplicationInfo applicationInfo = data.get(i);
156 final ComponentName component = applicationInfo.intent.getComponent();
157 if (packageName.equals(component.getPackageName())) {
158 removed.add(applicationInfo);
159 mIconCache.remove(component);
160 data.remove(i);
161 }
162 }
Joe Onorato9c1289c2009-08-17 11:03:03 -0400163 }
164 }
165
166 /**
167 * Query the package manager for MAIN/LAUNCHER activities in the supplied package.
168 */
169 private static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
170 final PackageManager packageManager = context.getPackageManager();
171
172 final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
173 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackborn2d86dfe2010-07-24 16:48:01 -0700174 mainIntent.setPackage(packageName);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400175
176 final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
Dianne Hackborn2d86dfe2010-07-24 16:48:01 -0700177 return apps != null ? apps : new ArrayList<ResolveInfo>();
Joe Onorato9c1289c2009-08-17 11:03:03 -0400178 }
179
180 /**
181 * Returns whether <em>apps</em> contains <em>component</em>.
182 */
183 private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
184 final String className = component.getClassName();
185 for (ResolveInfo info : apps) {
186 final ActivityInfo activityInfo = info.activityInfo;
187 if (activityInfo.name.equals(className)) {
188 return true;
189 }
190 }
191 return false;
192 }
193
194 /**
Joe Onoratod65d08e2010-04-20 15:43:37 -0400195 * Returns whether <em>apps</em> contains <em>component</em>.
196 */
197 private static boolean findActivity(ArrayList<ApplicationInfo> apps, ComponentName component) {
198 final int N = apps.size();
199 for (int i=0; i<N; i++) {
200 final ApplicationInfo info = apps.get(i);
201 if (info.componentName.equals(component)) {
202 return true;
203 }
204 }
205 return false;
206 }
207
208 /**
Joe Onorato9c1289c2009-08-17 11:03:03 -0400209 * Find an ApplicationInfo object for the given packageName and className.
210 */
211 private ApplicationInfo findApplicationInfoLocked(String packageName, String className) {
212 for (ApplicationInfo info: data) {
213 final ComponentName component = info.intent.getComponent();
214 if (packageName.equals(component.getPackageName())
215 && className.equals(component.getClassName())) {
216 return info;
217 }
218 }
219 return null;
220 }
221}