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 java.util.ArrayList;
     20 import java.util.List;
     21 
     22 import android.content.ComponentName;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.pm.ActivityInfo;
     26 import android.content.pm.PackageManager;
     27 import android.content.pm.ResolveInfo;
     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         // This is more aggressive than it needs to be.
    119         mIconCache.flush();
    120     }
    121 
    122     /**
    123      * Add and remove icons for this package which has been updated.
    124      */
    125     public void updatePackage(Context context, String packageName) {
    126         final List<ResolveInfo> matches = findActivitiesForPackage(context, packageName);
    127         if (matches.size() > 0) {
    128             // Find disabled/removed activities and remove them from data and add them
    129             // to the removed list.
    130             for (int i = data.size() - 1; i >= 0; i--) {
    131                 final AppInfo applicationInfo = data.get(i);
    132                 final ComponentName component = applicationInfo.intent.getComponent();
    133                 if (packageName.equals(component.getPackageName())) {
    134                     if (!findActivity(matches, component)) {
    135                         removed.add(applicationInfo);
    136                         mIconCache.remove(component);
    137                         data.remove(i);
    138                     }
    139                 }
    140             }
    141 
    142             // Find enabled activities and add them to the adapter
    143             // Also updates existing activities with new labels/icons
    144             int count = matches.size();
    145             for (int i = 0; i < count; i++) {
    146                 final ResolveInfo info = matches.get(i);
    147                 AppInfo applicationInfo = findApplicationInfoLocked(
    148                         info.activityInfo.applicationInfo.packageName,
    149                         info.activityInfo.name);
    150                 if (applicationInfo == null) {
    151                     add(new AppInfo(context.getPackageManager(), info, mIconCache, null));
    152                 } else {
    153                     mIconCache.remove(applicationInfo.componentName);
    154                     mIconCache.getTitleAndIcon(applicationInfo, info, null);
    155                     modified.add(applicationInfo);
    156                 }
    157             }
    158         } else {
    159             // Remove all data for this package.
    160             for (int i = data.size() - 1; i >= 0; i--) {
    161                 final AppInfo applicationInfo = data.get(i);
    162                 final ComponentName component = applicationInfo.intent.getComponent();
    163                 if (packageName.equals(component.getPackageName())) {
    164                     removed.add(applicationInfo);
    165                     mIconCache.remove(component);
    166                     data.remove(i);
    167                 }
    168             }
    169         }
    170     }
    171 
    172     /**
    173      * Query the package manager for MAIN/LAUNCHER activities in the supplied package.
    174      */
    175     static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
    176         final PackageManager packageManager = context.getPackageManager();
    177 
    178         final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    179         mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    180         mainIntent.setPackage(packageName);
    181 
    182         final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
    183         return apps != null ? apps : new ArrayList<ResolveInfo>();
    184     }
    185 
    186     /**
    187      * Returns whether <em>apps</em> contains <em>component</em>.
    188      */
    189     private static boolean findActivity(List<ResolveInfo> apps, ComponentName component) {
    190         final String className = component.getClassName();
    191         for (ResolveInfo info : apps) {
    192             final ActivityInfo activityInfo = info.activityInfo;
    193             if (activityInfo.name.equals(className)) {
    194                 return true;
    195             }
    196         }
    197         return false;
    198     }
    199 
    200     /**
    201      * Returns whether <em>apps</em> contains <em>component</em>.
    202      */
    203     private static boolean findActivity(ArrayList<AppInfo> apps, ComponentName component) {
    204         final int N = apps.size();
    205         for (int i=0; i<N; i++) {
    206             final AppInfo info = apps.get(i);
    207             if (info.componentName.equals(component)) {
    208                 return true;
    209             }
    210         }
    211         return false;
    212     }
    213 
    214     /**
    215      * Find an ApplicationInfo object for the given packageName and className.
    216      */
    217     private AppInfo findApplicationInfoLocked(String packageName, String className) {
    218         for (AppInfo info: data) {
    219             final ComponentName component = info.intent.getComponent();
    220             if (packageName.equals(component.getPackageName())
    221                     && className.equals(component.getClassName())) {
    222                 return info;
    223             }
    224         }
    225         return null;
    226     }
    227 }
    228