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