Home | History | Annotate | Download | only in model
      1 
      2 package com.android.launcher3.model;
      3 
      4 import android.content.ComponentName;
      5 import android.content.Context;
      6 import android.content.pm.ResolveInfo;
      7 import android.util.Log;
      8 
      9 import com.android.launcher3.AppFilter;
     10 import com.android.launcher3.IconCache;
     11 import com.android.launcher3.LauncherAppWidgetProviderInfo;
     12 import com.android.launcher3.Utilities;
     13 import com.android.launcher3.compat.AlphabeticIndexCompat;
     14 import com.android.launcher3.compat.AppWidgetManagerCompat;
     15 import com.android.launcher3.compat.UserHandleCompat;
     16 
     17 import java.util.ArrayList;
     18 import java.util.Collections;
     19 import java.util.Comparator;
     20 import java.util.HashMap;
     21 import java.util.List;
     22 
     23 /**
     24  * Widgets data model that is used by the adapters of the widget views and controllers.
     25  *
     26  * <p> The widgets and shortcuts are organized using package name as its index.
     27  */
     28 public class WidgetsModel {
     29 
     30     private static final String TAG = "WidgetsModel";
     31     private static final boolean DEBUG = false;
     32 
     33     /* List of packages that is tracked by this model. */
     34     private ArrayList<PackageItemInfo> mPackageItemInfos = new ArrayList<>();
     35 
     36     /* Map of widgets and shortcuts that are tracked per package. */
     37     private HashMap<PackageItemInfo, ArrayList<Object>> mWidgetsList = new HashMap<>();
     38 
     39     private ArrayList<Object> mRawList;
     40 
     41     private final AppWidgetManagerCompat mAppWidgetMgr;
     42     private final Comparator mWidgetAndShortcutNameComparator;
     43     private final Comparator mAppNameComparator;
     44     private final IconCache mIconCache;
     45     private final AppFilter mAppFilter;
     46     private AlphabeticIndexCompat mIndexer;
     47 
     48     public WidgetsModel(Context context,  IconCache iconCache, AppFilter appFilter) {
     49         mAppWidgetMgr = AppWidgetManagerCompat.getInstance(context);
     50         mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context);
     51         mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator();
     52         mIconCache = iconCache;
     53         mAppFilter = appFilter;
     54         mIndexer = new AlphabeticIndexCompat(context);
     55     }
     56 
     57     private WidgetsModel(WidgetsModel model) {
     58         mAppWidgetMgr = model.mAppWidgetMgr;
     59         mPackageItemInfos = (ArrayList<PackageItemInfo>) model.mPackageItemInfos.clone();
     60         mWidgetsList = (HashMap<PackageItemInfo, ArrayList<Object>>) model.mWidgetsList.clone();
     61         mRawList = (ArrayList<Object>) model.mRawList.clone();
     62         mWidgetAndShortcutNameComparator = model.mWidgetAndShortcutNameComparator;
     63         mAppNameComparator = model.mAppNameComparator;
     64         mIconCache = model.mIconCache;
     65         mAppFilter = model.mAppFilter;
     66     }
     67 
     68     // Access methods that may be deleted if the private fields are made package-private.
     69     public int getPackageSize() {
     70         if (mPackageItemInfos == null) {
     71             return 0;
     72         }
     73         return mPackageItemInfos.size();
     74     }
     75 
     76     // Access methods that may be deleted if the private fields are made package-private.
     77     public PackageItemInfo getPackageItemInfo(int pos) {
     78         if (pos >= mPackageItemInfos.size() || pos < 0) {
     79             return null;
     80         }
     81         return mPackageItemInfos.get(pos);
     82     }
     83 
     84     public List<Object> getSortedWidgets(int pos) {
     85         return mWidgetsList.get(mPackageItemInfos.get(pos));
     86     }
     87 
     88     public ArrayList<Object> getRawList() {
     89         return mRawList;
     90     }
     91 
     92     public void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
     93         Utilities.assertWorkerThread();
     94         mRawList = rawWidgetsShortcuts;
     95         if (DEBUG) {
     96             Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
     97         }
     98 
     99         // Temporary list for {@link PackageItemInfos} to avoid having to go through
    100         // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList}
    101         HashMap<String, PackageItemInfo> tmpPackageItemInfos = new HashMap<>();
    102 
    103         // clear the lists.
    104         mWidgetsList.clear();
    105         mPackageItemInfos.clear();
    106 
    107         // add and update.
    108         for (Object o: rawWidgetsShortcuts) {
    109             String packageName = "";
    110             UserHandleCompat userHandle = null;
    111             ComponentName componentName = null;
    112             if (o instanceof LauncherAppWidgetProviderInfo) {
    113                 LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o;
    114                 componentName = widgetInfo.provider;
    115                 packageName = widgetInfo.provider.getPackageName();
    116                 userHandle = mAppWidgetMgr.getUser(widgetInfo);
    117             } else if (o instanceof ResolveInfo) {
    118                 ResolveInfo resolveInfo = (ResolveInfo) o;
    119                 componentName = new ComponentName(resolveInfo.activityInfo.packageName,
    120                         resolveInfo.activityInfo.name);
    121                 packageName = resolveInfo.activityInfo.packageName;
    122                 userHandle = UserHandleCompat.myUserHandle();
    123             }
    124 
    125             if (componentName == null || userHandle == null) {
    126                 Log.e(TAG, String.format("Widget cannot be set for %s.", o.getClass().toString()));
    127                 continue;
    128             }
    129             if (mAppFilter != null && !mAppFilter.shouldShowApp(componentName)) {
    130                 if (DEBUG) {
    131                     Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
    132                         packageName));
    133                 }
    134                 continue;
    135             }
    136 
    137             PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName);
    138             ArrayList<Object> widgetsShortcutsList = mWidgetsList.get(pInfo);
    139             if (widgetsShortcutsList != null) {
    140                 widgetsShortcutsList.add(o);
    141             } else {
    142                 widgetsShortcutsList = new ArrayList<Object>();
    143                 widgetsShortcutsList.add(o);
    144                 pInfo = new PackageItemInfo(packageName);
    145                 mIconCache.getTitleAndIconForApp(packageName, userHandle,
    146                         true /* userLowResIcon */, pInfo);
    147                 pInfo.titleSectionName = mIndexer.computeSectionName(pInfo.title);
    148                 mWidgetsList.put(pInfo, widgetsShortcutsList);
    149                 tmpPackageItemInfos.put(packageName,  pInfo);
    150                 mPackageItemInfos.add(pInfo);
    151             }
    152         }
    153 
    154         // sort.
    155         Collections.sort(mPackageItemInfos, mAppNameComparator);
    156         for (PackageItemInfo p: mPackageItemInfos) {
    157             Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator);
    158         }
    159     }
    160 
    161     /**
    162      * Create a snapshot of the widgets model.
    163      * <p>
    164      * Usage case: view binding without being modified from package updates.
    165      */
    166     @Override
    167     public WidgetsModel clone(){
    168         return new WidgetsModel(this);
    169     }
    170 }