From 2bd3d7d1cb5e4d8d826982d11b456739fed6b817 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Thu, 21 May 2015 13:04:53 -0700 Subject: Load PackageItemInfo in background thread to prevent ANR - Decoupled widget model from widget view, and placed the creation to LauncherModel. - As a result packagemanager operation, iconcache retrieval is all done inside LauncherModel on background thread b/21311085 b/21325319 Change-Id: I294698527db58b89f3da558090a367530c058776 --- src/com/android/launcher3/BubbleTextView.java | 2 +- src/com/android/launcher3/IconCache.java | 2 +- src/com/android/launcher3/Launcher.java | 19 ++-- src/com/android/launcher3/LauncherModel.java | 16 ++- src/com/android/launcher3/Utilities.java | 9 ++ src/com/android/launcher3/WidgetPreviewLoader.java | 3 +- .../android/launcher3/model/PackageItemInfo.java | 58 ++++++++++ src/com/android/launcher3/model/WidgetsModel.java | 125 +++++++++++++++++++++ .../android/launcher3/widget/PackageItemInfo.java | 58 ---------- .../launcher3/widget/WidgetsContainerView.java | 22 +--- .../launcher3/widget/WidgetsListAdapter.java | 2 + src/com/android/launcher3/widget/WidgetsModel.java | 122 -------------------- 12 files changed, 221 insertions(+), 217 deletions(-) create mode 100644 src/com/android/launcher3/model/PackageItemInfo.java create mode 100644 src/com/android/launcher3/model/WidgetsModel.java delete mode 100644 src/com/android/launcher3/widget/PackageItemInfo.java delete mode 100644 src/com/android/launcher3/widget/WidgetsModel.java diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 3b3b9bf9f..d5300095b 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -38,7 +38,7 @@ import android.view.ViewParent; import android.widget.TextView; import com.android.launcher3.IconCache.IconLoadRequest; -import com.android.launcher3.widget.PackageItemInfo; +import com.android.launcher3.model.PackageItemInfo; /** * TextView that draws a bubble behind the text. We cannot use a LineBackgroundSpan diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index 1fac5a1c2..a38757991 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -42,9 +42,9 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; +import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.Thunk; -import com.android.launcher3.widget.PackageItemInfo; import java.util.Collection; import java.util.HashMap; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7b7b61795..59ca97865 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -102,6 +102,7 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; +import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddWidgetInfo; @@ -268,8 +269,9 @@ public class Launcher extends Activity // Main container view for the all apps screen. @Thunk AppsContainerView mAppsView; - // Main container view for the widget tray screen. - private WidgetsContainerView mWidgetsView; + // Main container view and the model for the widget tray screen. + @Thunk WidgetsContainerView mWidgetsView; + @Thunk WidgetsModel mWidgetsModel; private boolean mAutoAdvanceRunning = false; private AppWidgetHostView mQsb; @@ -4365,23 +4367,22 @@ public class Launcher extends Activity } } - @Thunk ArrayList mWidgetsAndShortcuts; private Runnable mBindPackagesUpdatedRunnable = new Runnable() { public void run() { - bindAllPackages(mWidgetsAndShortcuts); + bindAllPackages(mWidgetsModel); } }; @Override - public void bindAllPackages(final ArrayList widgetsAndShortcuts) { + public void bindAllPackages(final WidgetsModel model) { if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) { - mWidgetsAndShortcuts = widgetsAndShortcuts; + mWidgetsModel = model; return; } - if (mWidgetsView != null && widgetsAndShortcuts != null) { - mWidgetsView.addWidgets(widgetsAndShortcuts, getPackageManager()); - mWidgetsAndShortcuts = null; + if (mWidgetsView != null && model != null) { + mWidgetsView.addWidgets(model); + mWidgetsModel = null; } } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 3e05f57b9..500253826 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -58,6 +58,7 @@ import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; +import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.ManagedProfileHeuristic; @@ -203,7 +204,7 @@ public class LauncherModel extends BroadcastReceiver public void bindRestoreItemsChange(HashSet updates); public void bindComponentsRemoved(ArrayList packageNames, ArrayList appInfos, UserHandleCompat user, int reason); - public void bindAllPackages(ArrayList widgetsAndShortcuts); + public void bindAllPackages(WidgetsModel model); public void bindSearchablesChanged(); public boolean isAllAppsButtonRank(int rank); public void onPageBoundSynchronously(int page); @@ -3344,18 +3345,19 @@ public class LauncherModel extends BroadcastReceiver runOnWorkerThread(new Runnable(){ @Override public void run() { - final ArrayList list = getWidgetsAndShortcuts(context, refresh); + final WidgetsModel model = createWidgetsModel(context, refresh); mHandler.post(new Runnable() { @Override public void run() { Callbacks cb = getCallback(); if (callbacks == cb && cb != null) { - callbacks.bindAllPackages(list); + callbacks.bindAllPackages(model); } } }); // update the Widget entries inside DB on the worker thread. - LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(list); + LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews( + model.getRawList()); } }); } @@ -3365,13 +3367,15 @@ public class LauncherModel extends BroadcastReceiver * * @see #loadAndBindWidgetsAndShortcuts */ - private ArrayList getWidgetsAndShortcuts(Context context, boolean refresh) { + private WidgetsModel createWidgetsModel(Context context, boolean refresh) { PackageManager packageManager = context.getPackageManager(); final ArrayList widgetsAndShortcuts = new ArrayList(); widgetsAndShortcuts.addAll(getWidgetProviders(context, refresh)); Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0)); - return widgetsAndShortcuts; + WidgetsModel model = new WidgetsModel(context); + model.addWidgetsAndShortcuts(widgetsAndShortcuts); + return model; } @Thunk static boolean isPackageDisabled(Context context, String packageName, diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 6734fdc0d..1f8a6f2a5 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -44,6 +44,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.PaintDrawable; import android.os.Build; +import android.os.Process; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -57,6 +58,8 @@ import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; +import junit.framework.Assert; + /** * Various utilities shared amongst the Launcher's classes. */ @@ -641,4 +644,10 @@ public final class Utilities { return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) && (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); } + + public static void assertWorkerThread() { + if (LauncherAppState.isDogfoodBuild()) { + Assert.assertTrue(LauncherModel.sWorkerThread.getThreadId() == Process.myTid()); + } + } } diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index bbcdaae39..5ee1f2615 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -206,8 +206,7 @@ public class WidgetPreviewLoader { * This ensures that we remove entries for packages which changed while the launcher was dead. */ public void removeObsoletePreviews(ArrayList list) { - // This method should always be called from the worker thread. - Assert.assertTrue(LauncherModel.sWorkerThread.getThreadId() == Process.myTid()); + Utilities.assertWorkerThread(); LongSparseArray userIdCache = new LongSparseArray<>(); LongSparseArray> validPackages = new LongSparseArray<>(); diff --git a/src/com/android/launcher3/model/PackageItemInfo.java b/src/com/android/launcher3/model/PackageItemInfo.java new file mode 100644 index 000000000..0f0134ae3 --- /dev/null +++ b/src/com/android/launcher3/model/PackageItemInfo.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.model; + +import android.content.ComponentName; +import android.graphics.Bitmap; + +import com.android.launcher3.ItemInfo; + +import java.util.Arrays; + +/** + * Represents a {@link Package} in the widget tray section. + */ +public class PackageItemInfo extends ItemInfo { + private static final String TAG = "PackageInfo"; + + /** + * A bitmap version of the application icon. + */ + public Bitmap iconBitmap; + + /** + * Indicates whether we're using a low res icon + */ + public boolean usingLowResIcon; + + public String packageName; + + int flags = 0; + + PackageItemInfo(String packageName) { + this.packageName = packageName; + } + + @Override + public String toString() { + return "PackageItemInfo(title=" + title + " id=" + this.id + + " type=" + this.itemType + " container=" + this.container + + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY + + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) + + " user=" + user + ")"; + } +} diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java new file mode 100644 index 000000000..b72b98126 --- /dev/null +++ b/src/com/android/launcher3/model/WidgetsModel.java @@ -0,0 +1,125 @@ + +package com.android.launcher3.model; + +import android.content.Context; +import android.content.pm.ResolveInfo; +import android.os.Handler; +import android.os.Process; +import android.util.Log; + +import com.android.launcher3.IconCache; +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherAppWidgetProviderInfo; + +import com.android.launcher3.LauncherModel; +import com.android.launcher3.Utilities; +import com.android.launcher3.compat.UserHandleCompat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Widgets data model that is used by the adapters of the widget views and controllers. + * + *

The widgets and shortcuts are organized using package name as its index. + */ +public class WidgetsModel { + + private static final String TAG = "WidgetsModel"; + private static final boolean DEBUG = false; + + /* List of packages that is tracked by this model. */ + private List mPackageItemInfos = new ArrayList<>(); + + /* Map of widgets and shortcuts that are tracked per package. */ + private Map> mWidgetsList = new HashMap<>(); + + private ArrayList mRawList; + + private final Comparator mWidgetAndShortcutNameComparator; + private final Comparator mAppNameComparator; + + private final IconCache mIconCache; + private final Handler mWorkerHandler; + + public WidgetsModel(Context context) { + mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context); + mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator(); + mIconCache = LauncherAppState.getInstance().getIconCache(); + mWorkerHandler = new Handler(LauncherModel.getWorkerLooper()); + } + + // Access methods that may be deleted if the private fields are made package-private. + public int getPackageSize() { + return mPackageItemInfos.size(); + } + + // Access methods that may be deleted if the private fields are made package-private. + public PackageItemInfo getPackageItemInfo(int pos) { + return mPackageItemInfos.get(pos); + } + + public List getSortedWidgets(int pos) { + return mWidgetsList.get(mPackageItemInfos.get(pos)); + } + + public ArrayList getRawList() { + return mRawList; + } + + public void addWidgetsAndShortcuts(ArrayList rawWidgetsShortcuts) { + Utilities.assertWorkerThread(); + mRawList = rawWidgetsShortcuts; + if (DEBUG) { + Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size()); + } + + // Temporary list for {@link PackageItemInfos} to avoid having to go through + // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList} + HashMap tmpPackageItemInfos = new HashMap<>(); + + // clear the lists. + mWidgetsList.clear(); + mPackageItemInfos.clear(); + + // add and update. + for (Object o: rawWidgetsShortcuts) { + String packageName = ""; + if (o instanceof LauncherAppWidgetProviderInfo) { + LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o; + packageName = widgetInfo.provider.getPackageName(); + } else if (o instanceof ResolveInfo) { + ResolveInfo resolveInfo = (ResolveInfo) o; + packageName = resolveInfo.activityInfo.packageName; + } else { + Log.e(TAG, String.format("addWidgetsAndShortcuts, nothing added for class=%s", + o.getClass().toString())); + } + + PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName); + ArrayList widgetsShortcutsList = mWidgetsList.get(pInfo); + if (widgetsShortcutsList != null) { + widgetsShortcutsList.add(o); + } else { + widgetsShortcutsList = new ArrayList(); + widgetsShortcutsList.add(o); + pInfo = new PackageItemInfo(packageName); + mIconCache.getTitleAndIconForApp(packageName, UserHandleCompat.myUserHandle(), + true /* userLowResIcon */, pInfo); + mWidgetsList.put(pInfo, widgetsShortcutsList); + tmpPackageItemInfos.put(packageName, pInfo); + mPackageItemInfos.add(pInfo); + } + } + + // sort. + Collections.sort(mPackageItemInfos, mAppNameComparator); + for (PackageItemInfo p: mPackageItemInfos) { + Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator); + } + } +} \ No newline at end of file diff --git a/src/com/android/launcher3/widget/PackageItemInfo.java b/src/com/android/launcher3/widget/PackageItemInfo.java deleted file mode 100644 index 8f45a7754..000000000 --- a/src/com/android/launcher3/widget/PackageItemInfo.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.widget; - -import android.content.ComponentName; -import android.graphics.Bitmap; - -import com.android.launcher3.ItemInfo; - -import java.util.Arrays; - -/** - * Represents a {@link Package} in the widget tray section. - */ -public class PackageItemInfo extends ItemInfo { - private static final String TAG = "PackageInfo"; - - /** - * A bitmap version of the application icon. - */ - public Bitmap iconBitmap; - - /** - * Indicates whether we're using a low res icon - */ - public boolean usingLowResIcon; - - public String packageName; - - int flags = 0; - - PackageItemInfo(String packageName) { - this.packageName = packageName; - } - - @Override - public String toString() { - return "PackageItemInfo(title=" + title + " id=" + this.id - + " type=" + this.itemType + " container=" + this.container - + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY - + " spanX=" + spanX + " spanY=" + spanY + " dropPos=" + Arrays.toString(dropPos) - + " user=" + user + ")"; - } -} diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java index 7a7895ff8..5a879faa0 100644 --- a/src/com/android/launcher3/widget/WidgetsContainerView.java +++ b/src/com/android/launcher3/widget/WidgetsContainerView.java @@ -17,7 +17,6 @@ package com.android.launcher3.widget; import android.content.Context; -import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -36,6 +35,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.DragController; import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget.DragObject; +import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.Folder; import com.android.launcher3.IconCache; import com.android.launcher3.ItemInfo; @@ -47,8 +47,6 @@ import com.android.launcher3.Utilities; import com.android.launcher3.WidgetPreviewLoader; import com.android.launcher3.Workspace; -import java.util.ArrayList; - /** * The widgets list view container. */ @@ -68,9 +66,6 @@ public class WidgetsContainerView extends BaseContainerView private DragController mDragController; private IconCache mIconCache; - /* Data model for the widget */ - private WidgetsModel mWidgets; - /* Recycler view related member variables */ private RecyclerView mView; private WidgetsListAdapter mAdapter; @@ -98,8 +93,6 @@ public class WidgetsContainerView extends BaseContainerView mDragController = mLauncher.getDragController(); mWidgetHostViewLoader = new WidgetHostViewLoader(mLauncher); mAdapter = new WidgetsListAdapter(context, this, this, mLauncher); - mWidgets = new WidgetsModel(context, mAdapter); - mAdapter.setWidgetsModel(mWidgets); mIconCache = (LauncherAppState.getInstance()).getIconCache(); if (DEBUG) { @@ -109,10 +102,6 @@ public class WidgetsContainerView extends BaseContainerView @Override protected void onFinishInflate() { - if (DEBUG) { - Log.d(TAG, String.format("onFinishInflate [widgets size=%d]", - mWidgets.getPackageSize())); - } mView = (RecyclerView) findViewById(R.id.widgets_list_view); mView.setAdapter(mAdapter); @@ -145,10 +134,6 @@ public class WidgetsContainerView extends BaseContainerView public void scrollToTop() { mView.scrollToPosition(0); - if (DEBUG) { - Log.d(TAG, String.format("scrollToTop, [widgets size=%d]", - mWidgets.getPackageSize())); - } } // @@ -374,8 +359,9 @@ public class WidgetsContainerView extends BaseContainerView /** * Initialize the widget data model. */ - public void addWidgets(ArrayList widgetsShortcuts, PackageManager pm) { - mWidgets.addWidgetsAndShortcuts(widgetsShortcuts, pm); + public void addWidgets(WidgetsModel model) { + mAdapter.setWidgetsModel(model); + mAdapter.notifyDataSetChanged(); } private WidgetPreviewLoader getWidgetPreviewLoader() { diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java index 3916c00d2..918ec1bda 100644 --- a/src/com/android/launcher3/widget/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java @@ -38,6 +38,8 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.R; import com.android.launcher3.WidgetPreviewLoader; +import com.android.launcher3.model.PackageItemInfo; +import com.android.launcher3.model.WidgetsModel; import java.util.List; diff --git a/src/com/android/launcher3/widget/WidgetsModel.java b/src/com/android/launcher3/widget/WidgetsModel.java deleted file mode 100644 index 5a920e8d4..000000000 --- a/src/com/android/launcher3/widget/WidgetsModel.java +++ /dev/null @@ -1,122 +0,0 @@ - -package com.android.launcher3.widget; - -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.support.v7.widget.RecyclerView; -import android.util.Log; - -import com.android.launcher3.IconCache; -import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherAppWidgetProviderInfo; -import com.android.launcher3.compat.UserHandleCompat; -import com.android.launcher3.model.AppNameComparator; -import com.android.launcher3.model.WidgetsAndShortcutNameComparator; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Widgets data model that is used by the adapters of the widget views and controllers. - * - *

The widgets and shortcuts are organized using package name as its index. - */ -public class WidgetsModel { - - private static final String TAG = "WidgetsModel"; - private static final boolean DEBUG = false; - - /* List of packages that is tracked by this model. */ - private List mPackageItemInfos = new ArrayList<>(); - - /* Map of widgets and shortcuts that are tracked per package. */ - private Map> mWidgetsList = new HashMap<>(); - - /* Notifies the adapter when data changes. */ - private RecyclerView.Adapter mAdapter; - - private Comparator mWidgetAndShortcutNameComparator; - private Comparator mAppNameComparator; - - private IconCache mIconCache; - - public WidgetsModel(Context context, RecyclerView.Adapter adapter) { - mAdapter = adapter; - mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context); - mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator(); - mIconCache = LauncherAppState.getInstance().getIconCache(); - } - - // Access methods that may be deleted if the private fields are made package-private. - public int getPackageSize() { - return mPackageItemInfos.size(); - } - - // Access methods that may be deleted if the private fields are made package-private. - public PackageItemInfo getPackageItemInfo(int pos) { - return mPackageItemInfos.get(pos); - } - - public List getSortedWidgets(int pos) { - return mWidgetsList.get(mPackageItemInfos.get(pos)); - } - - public void addWidgetsAndShortcuts(ArrayList widgetsShortcuts, PackageManager pm) { - if (DEBUG) { - Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + widgetsShortcuts.size()); - } - - // Temporary list for {@link PackageItemInfos} to avoid having to go through - // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList} - HashMap tmpPackageItemInfos = new HashMap<>(); - - // clear the lists. - mWidgetsList.clear(); - mPackageItemInfos.clear(); - - // add and update. - for (Object o: widgetsShortcuts) { - String packageName = ""; - if (o instanceof LauncherAppWidgetProviderInfo) { - LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o; - packageName = widgetInfo.provider.getPackageName(); - } else if (o instanceof ResolveInfo) { - ResolveInfo resolveInfo = (ResolveInfo) o; - packageName = resolveInfo.activityInfo.packageName; - } else { - Log.e(TAG, String.format("addWidgetsAndShortcuts, nothing added for class=%s", - o.getClass().toString())); - } - - PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName); - ArrayList widgetsShortcutsList = mWidgetsList.get(pInfo); - if (widgetsShortcutsList != null) { - widgetsShortcutsList.add(o); - } else { - widgetsShortcutsList = new ArrayList(); - widgetsShortcutsList.add(o); - - pInfo = new PackageItemInfo(packageName); - mIconCache.getTitleAndIconForApp(packageName, UserHandleCompat.myUserHandle(), - true /* useLowResIcon */, pInfo); - mWidgetsList.put(pInfo, widgetsShortcutsList); - tmpPackageItemInfos.put(packageName, pInfo); - mPackageItemInfos.add(pInfo); - } - } - - // sort. - Collections.sort(mPackageItemInfos, mAppNameComparator); - for (PackageItemInfo p: mPackageItemInfos) { - Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator); - } - - // notify. - mAdapter.notifyDataSetChanged(); - } -} \ No newline at end of file -- cgit v1.2.3