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