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