blob: 9d4c5b02a8715566f3374f150edbfac89d16caa5 [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
19import android.content.ComponentName;
Joe Onorato9c1289c2009-08-17 11:03:03 -040020import android.content.Intent;
21import android.content.Context;
22import android.content.pm.ActivityInfo;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
Joe Onorato9c1289c2009-08-17 11:03:03 -040025
Joe Onorato9c1289c2009-08-17 11:03:03 -040026import java.util.ArrayList;
Joe Onorato9c1289c2009-08-17 11:03:03 -040027import java.util.List;
28
29
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.
59 */
60 public void add(ApplicationInfo info) {
61 data.add(info);
62 added.add(info);
63 }
64
65 public void clear() {
66 data.clear();
67 // TODO: do we clear these too?
68 added.clear();
69 removed.clear();
70 modified.clear();
71 }
72
73 public int size() {
74 return data.size();
75 }
76
77 public ApplicationInfo get(int index) {
78 return data.get(index);
79 }
80
81 /**
82 * Add the icons for the supplied apk called packageName.
83 */
84 public void addPackage(Context context, String packageName) {
85 final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
86
87 if (matches.size() > 0) {
Joe Onorato9c1289c2009-08-17 11:03:03 -040088 for (ResolveInfo info : matches) {
Joe Onorato0589f0f2010-02-08 13:44:00 -080089 ApplicationInfo item = new ApplicationInfo(info, mIconCache);
Joe Onorato9c1289c2009-08-17 11:03:03 -040090 data.add(item);
91 added.add(item);
92 }
93 }
94 }
95
96 /**
97 * Remove the apps for the given apk identified by packageName.
98 */
99 public void removePackage(String packageName) {
100 final List<ApplicationInfo> data = this.data;
Romain Guy5c16f3e2010-01-12 17:24:58 -0800101 for (int i = data.size() - 1; i >= 0; i--) {
Joe Onorato9c1289c2009-08-17 11:03:03 -0400102 ApplicationInfo info = data.get(i);
103 final ComponentName component = info.intent.getComponent();
104 if (packageName.equals(component.getPackageName())) {
105 removed.add(info);
106 data.remove(i);
107 }
108 }
109 // This is more aggressive than it needs to be.
Joe Onorato0589f0f2010-02-08 13:44:00 -0800110 mIconCache.flush();
Joe Onorato9c1289c2009-08-17 11:03:03 -0400111 }
Joe Onorato0589f0f2010-02-08 13:44:00 -0800112
Joe Onorato9c1289c2009-08-17 11:03:03 -0400113 /**
114 * Add and remove icons for this package which has been updated.
115 */
116 public void updatePackage(Context context, String packageName) {
117 final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
118 if (matches.size() > 0) {
119 // Find disabled/removed activities and remove them from data and add them
120 // to the removed list.
Romain Guy5c16f3e2010-01-12 17:24:58 -0800121 for (int i = data.size() - 1; i >= 0; i--) {
Joe Onorato9c1289c2009-08-17 11:03:03 -0400122 final ApplicationInfo applicationInfo = data.get(i);
123 final ComponentName component = applicationInfo.intent.getComponent();
124 if (packageName.equals(component.getPackageName())) {
125 if (!findActivity(matches, component)) {
126 removed.add(applicationInfo);
Joe Onorato0589f0f2010-02-08 13:44:00 -0800127 mIconCache.remove(component);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400128 data.remove(i);
129 }
130 }
131 }
132
133 // Find enabled activities and add them to the adapter
134 // Also updates existing activities with new labels/icons
Joe Onorato9c1289c2009-08-17 11:03:03 -0400135 int count = matches.size();
Romain Guy5c16f3e2010-01-12 17:24:58 -0800136 for (int i = 0; i < count; i++) {
Joe Onorato9c1289c2009-08-17 11:03:03 -0400137 final ResolveInfo info = matches.get(i);
138 ApplicationInfo applicationInfo = findApplicationInfoLocked(
139 info.activityInfo.applicationInfo.packageName,
140 info.activityInfo.name);
141 if (applicationInfo == null) {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800142 applicationInfo = new ApplicationInfo(info, mIconCache);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400143 data.add(applicationInfo);
144 added.add(applicationInfo);
145 } else {
Joe Onorato0589f0f2010-02-08 13:44:00 -0800146 mIconCache.remove(applicationInfo.componentName);
147 mIconCache.getTitleAndIcon(applicationInfo, info);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400148 modified.add(applicationInfo);
149 }
150 }
151 }
152 }
153
154 /**
155 * Query the package manager for MAIN/LAUNCHER activities in the supplied package.
156 */
157 private static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
158 final PackageManager packageManager = context.getPackageManager();
159
160 final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
161 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
162
163 final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
164 final List<ResolveInfo> matches = new ArrayList<ResolveInfo>();
165
166 if (apps != null) {
167 // Find all activities that match the packageName
168 int count = apps.size();
169 for (int i = 0; i < count; i++) {
170 final ResolveInfo info = apps.get(i);
171 final ActivityInfo activityInfo = info.activityInfo;
172 if (packageName.equals(activityInfo.packageName)) {
173 matches.add(info);
174 }
175 }
176 }
177
178 return matches;
179 }
180
181 /**
182 * Returns whether <em>apps</em> contains <em>component</em>.
183 */
184 private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
185 final String className = component.getClassName();
186 for (ResolveInfo info : apps) {
187 final ActivityInfo activityInfo = info.activityInfo;
188 if (activityInfo.name.equals(className)) {
189 return true;
190 }
191 }
192 return false;
193 }
194
195 /**
196 * Find an ApplicationInfo object for the given packageName and className.
197 */
198 private ApplicationInfo findApplicationInfoLocked(String packageName, String className) {
199 for (ApplicationInfo info: data) {
200 final ComponentName component = info.intent.getComponent();
201 if (packageName.equals(component.getPackageName())
202 && className.equals(component.getClassName())) {
203 return info;
204 }
205 }
206 return null;
207 }
208}