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.launcher2; 18 19 import android.content.ComponentName; 20 import android.content.ContentResolver; 21 import android.content.ContentValues; 22 import android.content.Intent; 23 import android.content.Context; 24 import android.content.pm.ActivityInfo; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.content.res.Resources; 28 import android.database.Cursor; 29 import android.graphics.Bitmap; 30 import android.graphics.BitmapFactory; 31 import android.graphics.drawable.Drawable; 32 import android.net.Uri; 33 import android.util.Log; 34 import android.os.Process; 35 36 import java.lang.ref.WeakReference; 37 import java.util.ArrayList; 38 import java.util.HashMap; 39 import java.util.List; 40 41 42 /** 43 * Stores the list of all applications for the all apps view. 44 */ 45 class AllAppsList { 46 public static final int DEFAULT_APPLICATIONS_NUMBER = 42; 47 48 /** The list off all apps. */ 49 public ArrayList<ApplicationInfo> data = new ArrayList(DEFAULT_APPLICATIONS_NUMBER); 50 /** The list of apps that have been added since the last notify() call. */ 51 public ArrayList<ApplicationInfo> added = new ArrayList(DEFAULT_APPLICATIONS_NUMBER); 52 /** The list of apps that have been removed since the last notify() call. */ 53 public ArrayList<ApplicationInfo> removed = new ArrayList(); 54 /** The list of apps that have been modified since the last notify() call. */ 55 public ArrayList<ApplicationInfo> modified = new ArrayList(); 56 57 /** 58 * Boring constructor. 59 */ AllAppsList()60 public AllAppsList() { 61 } 62 63 /** 64 * Add the supplied ApplicationInfo objects to the list, and enqueue it into the 65 * list to broadcast when notify() is called. 66 */ add(ApplicationInfo info)67 public void add(ApplicationInfo info) { 68 data.add(info); 69 added.add(info); 70 } 71 clear()72 public void clear() { 73 data.clear(); 74 // TODO: do we clear these too? 75 added.clear(); 76 removed.clear(); 77 modified.clear(); 78 } 79 size()80 public int size() { 81 return data.size(); 82 } 83 get(int index)84 public ApplicationInfo get(int index) { 85 return data.get(index); 86 } 87 88 /** 89 * Add the icons for the supplied apk called packageName. 90 */ addPackage(Context context, String packageName)91 public void addPackage(Context context, String packageName) { 92 final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName); 93 94 if (matches.size() > 0) { 95 Utilities.BubbleText bubble = new Utilities.BubbleText(context); 96 for (ResolveInfo info : matches) { 97 ApplicationInfo item = AppInfoCache.cache(info, context, bubble); 98 data.add(item); 99 added.add(item); 100 } 101 } 102 } 103 104 /** 105 * Remove the apps for the given apk identified by packageName. 106 */ removePackage(String packageName)107 public void removePackage(String packageName) { 108 final List<ApplicationInfo> data = this.data; 109 for (int i=data.size()-1; i>=0; i--) { 110 ApplicationInfo info = data.get(i); 111 final ComponentName component = info.intent.getComponent(); 112 if (packageName.equals(component.getPackageName())) { 113 removed.add(info); 114 data.remove(i); 115 } 116 } 117 // This is more aggressive than it needs to be. 118 AppInfoCache.flush(); 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 ApplicationInfo 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 AppInfoCache.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 Utilities.BubbleText bubble = new Utilities.BubbleText(context); 144 int count = matches.size(); 145 for (int i=0; i<count; i++) { 146 final ResolveInfo info = matches.get(i); 147 ApplicationInfo applicationInfo = findApplicationInfoLocked( 148 info.activityInfo.applicationInfo.packageName, 149 info.activityInfo.name); 150 if (applicationInfo == null) { 151 applicationInfo = AppInfoCache.cache(info, context, bubble); 152 data.add(applicationInfo); 153 added.add(applicationInfo); 154 } else { 155 AppInfoCache.update(info, applicationInfo, context); 156 modified.add(applicationInfo); 157 } 158 } 159 } 160 } 161 162 /** 163 * Query the package manager for MAIN/LAUNCHER activities in the supplied package. 164 */ findActivitiesForPackage(Context context, String packageName)165 private static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) { 166 final PackageManager packageManager = context.getPackageManager(); 167 168 final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 169 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 170 171 final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0); 172 final List<ResolveInfo> matches = new ArrayList<ResolveInfo>(); 173 174 if (apps != null) { 175 // Find all activities that match the packageName 176 int count = apps.size(); 177 for (int i = 0; i < count; i++) { 178 final ResolveInfo info = apps.get(i); 179 final ActivityInfo activityInfo = info.activityInfo; 180 if (packageName.equals(activityInfo.packageName)) { 181 matches.add(info); 182 } 183 } 184 } 185 186 return matches; 187 } 188 189 /** 190 * Returns whether <em>apps</em> contains <em>component</em>. 191 */ findActivity(List<ResolveInfo> apps, ComponentName component)192 private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) { 193 final String className = component.getClassName(); 194 for (ResolveInfo info : apps) { 195 final ActivityInfo activityInfo = info.activityInfo; 196 if (activityInfo.name.equals(className)) { 197 return true; 198 } 199 } 200 return false; 201 } 202 203 /** 204 * Find an ApplicationInfo object for the given packageName and className. 205 */ findApplicationInfoLocked(String packageName, String className)206 private ApplicationInfo findApplicationInfoLocked(String packageName, String className) { 207 for (ApplicationInfo info: data) { 208 final ComponentName component = info.intent.getComponent(); 209 if (packageName.equals(component.getPackageName()) 210 && className.equals(component.getClassName())) { 211 return info; 212 } 213 } 214 return null; 215 } 216 } 217