From 1ed747a4c07101793322c13a36dd547df4a3aa50 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 3 May 2011 16:18:34 -0700 Subject: Testing mixing shortcuts into widgets pane. - Initial changes adding LRU cache to widget pane to speed up getting widget previews. Change-Id: If9ed479ba8f2fb321b3ff8c384ac5a9f87d4c689 --- .../android/launcher2/AppsCustomizePagedView.java | 188 +++++++++++++++------ src/com/android/launcher2/LauncherModel.java | 20 +++ src/com/android/launcher2/PagedViewWidget.java | 20 +++ 3 files changed, 181 insertions(+), 47 deletions(-) (limited to 'src/com/android') diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java index 5f86f7e2f..2bd2e91bd 100644 --- a/src/com/android/launcher2/AppsCustomizePagedView.java +++ b/src/com/android/launcher2/AppsCustomizePagedView.java @@ -37,10 +37,10 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; +import android.util.LruCache; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -74,14 +74,20 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // Content private ContentType mContentType; private ArrayList mApps; - private List mWidgets; - private List mShortcuts; + private List mWidgets; + + // Caching + private Drawable mDefaultWidgetBackground; + private final int sWidgetPreviewCacheSize = 1 * 1024 * 1024; // 1 MiB + private LruCache mWidgetPreviewCache; // Dimens private int mContentWidth; private int mMaxWidgetSpan, mMinWidgetSpan; private int mWidgetCellWidthGap, mWidgetCellHeightGap; private int mWidgetCountX, mWidgetCountY; + private final int mWidgetPreviewIconPaddedDimension; + private final float sWidgetPreviewIconPaddingPercentage = 0.25f; private PagedViewCellLayout mWidgetSpacingLayout; // Animations @@ -95,8 +101,16 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen mPackageManager = context.getPackageManager(); mContentType = ContentType.Applications; mApps = new ArrayList(); - mWidgets = new ArrayList(); - mShortcuts = new ArrayList(); + mWidgets = new ArrayList(); + mWidgetPreviewCache = new LruCache(sWidgetPreviewCacheSize) { + protected int sizeOf(Object key, Bitmap value) { + return value.getByteCount(); + } + }; + + // Save the default widget preview background + Resources resources = context.getResources(); + mDefaultWidgetBackground = resources.getDrawable(R.drawable.default_widget_preview); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, 0, 0); mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6); @@ -121,6 +135,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // preview can be before applying the widget scaling mMinWidgetSpan = 1; mMaxWidgetSpan = 3; + + // The padding on the non-matched dimension for the default widget preview icons + // (top + bottom) + int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size); + mWidgetPreviewIconPaddedDimension = + (int) (iconSize * (1 + (2 * sWidgetPreviewIconPaddingPercentage))); } @Override @@ -134,14 +154,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } public void onPackagesUpdated() { - // Get the list of widgets - mWidgets = AppWidgetManager.getInstance(mLauncher).getInstalledProviders(); - Collections.sort(mWidgets, LauncherModel.WIDGET_NAME_COMPARATOR); - - // Get the list of shortcuts + // Get the list of widgets and shortcuts + mWidgets.clear(); + mWidgets.addAll(AppWidgetManager.getInstance(mLauncher).getInstalledProviders()); Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); - mShortcuts = mPackageManager.queryIntentActivities(shortcutsIntent, 0); - Collections.sort(mShortcuts, new LauncherModel.ShortcutNameComparator(mPackageManager)); + mWidgets.addAll(mPackageManager.queryIntentActivities(shortcutsIntent, 0)); + Collections.sort(mWidgets, + new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager)); } /** @@ -338,23 +357,38 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen private void beginDraggingWidget(View v) { // Get the widget preview as the drag representation ImageView image = (ImageView) v.findViewById(R.id.widget_preview); - PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag(); + PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag(); // Compose the drag image + Bitmap b; Drawable preview = image.getDrawable(); int w = preview.getIntrinsicWidth(); int h = preview.getIntrinsicHeight(); - Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - renderDrawableToBitmap(preview, b, 0, 0, w, h, 1, 1); + if (createItemInfo instanceof PendingAddWidgetInfo) { + PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo; + int[] spanXY = CellLayout.rectToCell(getResources(), + createWidgetInfo.minWidth, createWidgetInfo.minHeight, null); + createItemInfo.spanX = spanXY[0]; + createItemInfo.spanY = spanXY[1]; + + b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + renderDrawableToBitmap(preview, b, 0, 0, w, h, 1, 1); + } else { + // Workaround for the fact that we don't keep the original ResolveInfo associated with + // the shortcut around. To get the icon, we just render the preview image (which has + // the shortcut icon) to a new drag bitmap that clips the non-icon space. + b = Bitmap.createBitmap(mWidgetPreviewIconPaddedDimension, + mWidgetPreviewIconPaddedDimension, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(b); + preview.draw(c); + createItemInfo.spanX = createItemInfo.spanY = 1; + } // Start the drag - int[] spanXY = CellLayout.rectToCell(getResources(), - createWidgetInfo.minWidth, createWidgetInfo.minHeight, null); - createWidgetInfo.spanX = spanXY[0]; - createWidgetInfo.spanY = spanXY[1]; mLauncher.lockScreenOrientation(); - mLauncher.getWorkspace().onDragStartedWithItemSpans(spanXY[0], spanXY[1], b); - mDragController.startDrag(image, b, this, createWidgetInfo, + mLauncher.getWorkspace().onDragStartedWithItemSpans(createItemInfo.spanX, + createItemInfo.spanY, b); + mDragController.startDrag(image, b, this, createItemInfo, DragController.DRAG_ACTION_COPY, null); b.recycle(); } @@ -502,8 +536,40 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen d.setBounds(oldBounds); // Restore the bounds c.restore(); } + private FastBitmapDrawable getShortcutPreview(ResolveInfo info, int cellWidth, int cellHeight) { + // Return the cached version if necessary + Bitmap cachedBitmap = mWidgetPreviewCache.get(info); + if (cachedBitmap != null) { + return new FastBitmapDrawable(cachedBitmap); + } + + Resources resources = mLauncher.getResources(); + int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size); + // We only need to make it wide enough so as not allow the preview to be scaled + int expectedWidth = cellWidth; + int expectedHeight = mWidgetPreviewIconPaddedDimension; + int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage); + + // Render the icon + Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888); + IconCache cache = ((LauncherApplication) mLauncher.getApplication()).getIconCache(); + Drawable icon = cache.getFullResIcon(info, mPackageManager); + renderDrawableToBitmap(mDefaultWidgetBackground, preview, 0, 0, + mWidgetPreviewIconPaddedDimension, mWidgetPreviewIconPaddedDimension, 1f, 1f); + renderDrawableToBitmap(icon, preview, offset, offset, iconSize, iconSize, 1f, 1f); + FastBitmapDrawable iconDrawable = new FastBitmapDrawable(preview); + iconDrawable.setBounds(0, 0, expectedWidth, expectedHeight); + mWidgetPreviewCache.put(info, preview); + return iconDrawable; + } private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info, int cellHSpan, int cellVSpan, int cellWidth, int cellHeight) { + // Return the cached version if necessary + Bitmap cachedBitmap = mWidgetPreviewCache.get(info); + if (cachedBitmap != null) { + return new FastBitmapDrawable(cachedBitmap); + } + // Calculate the size of the drawable cellHSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellHSpan)); cellVSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellVSpan)); @@ -543,23 +609,29 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen renderDrawableToBitmap(drawable, preview, 0, 0, newWidth, newHeight, 1f, 1f); newDrawable = new FastBitmapDrawable(preview); newDrawable.setBounds(0, 0, newWidth, newHeight); + mWidgetPreviewCache.put(info, preview); } } // Generate a preview image if we couldn't load one if (drawable == null) { - // The icon itself takes up space, so update expected width/height to have min of 2 - cellHSpan = Math.max(2, cellHSpan); - cellVSpan = Math.max(2, cellVSpan); - expectedWidth = (int) (widgetPreviewScale - * mWidgetSpacingLayout.estimateCellWidth(cellHSpan)); - expectedHeight = (int) (widgetPreviewScale - * mWidgetSpacingLayout.estimateCellHeight(cellVSpan)); + Resources resources = mLauncher.getResources(); + int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size); + + // Specify the dimensions of the bitmap + if (info.minWidth >= info.minHeight) { + expectedWidth = cellWidth; + expectedHeight = mWidgetPreviewIconPaddedDimension; + } else { + // Note that in vertical widgets, we might not have enough space due to the text + // label, so be conservative and use the width as a height bound + expectedWidth = mWidgetPreviewIconPaddedDimension; + expectedHeight = cellWidth; + } Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888); - Resources resources = mLauncher.getResources(); - Drawable background = resources.getDrawable(R.drawable.default_widget_preview); - renderDrawableToBitmap(background, preview, 0, 0, expectedWidth, expectedHeight, 1f,1f); + renderDrawableToBitmap(mDefaultWidgetBackground, preview, 0, 0, expectedWidth, + expectedHeight, 1f,1f); // Draw the icon in the top left corner try { @@ -567,13 +639,13 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen if (info.icon > 0) icon = mPackageManager.getDrawable(packageName, info.icon, null); if (icon == null) icon = resources.getDrawable(R.drawable.ic_launcher_application); - int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size); - int offset = iconSize / 4; + int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage); renderDrawableToBitmap(icon, preview, offset, offset, iconSize, iconSize, 1f, 1f); } catch (Resources.NotFoundException e) {} newDrawable = new FastBitmapDrawable(preview); newDrawable.setBounds(0, 0, expectedWidth, expectedHeight); + mWidgetPreviewCache.put(info, preview); } return newDrawable; } @@ -602,16 +674,31 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen int cellHeight = ((mWidgetSpacingLayout.getContentHeight() - mPageLayoutHeightGap - ((mWidgetCountY - 1) * mWidgetCellHeightGap)) / mWidgetCountY); for (int i = 0; i < Math.min(numWidgetsPerPage, mWidgets.size() - offset); ++i) { - AppWidgetProviderInfo info = (AppWidgetProviderInfo) mWidgets.get(offset + i); - PendingAddWidgetInfo createItemInfo = new PendingAddWidgetInfo(info, null, null); - final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth, - info.minHeight, null); - FastBitmapDrawable preview = getWidgetPreview(info, cellSpans[0], cellSpans[1], - cellWidth, cellHeight); + Object rawInfo = mWidgets.get(offset + i); + PendingAddItemInfo createItemInfo = null; PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate( R.layout.apps_customize_widget, layout, false); - widget.applyFromAppWidgetProviderInfo(info, preview, -1, cellSpans, null, false); - widget.setTag(createItemInfo); + if (rawInfo instanceof AppWidgetProviderInfo) { + // Fill in the widget information + AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo; + createItemInfo = new PendingAddWidgetInfo(info, null, null); + final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth, + info.minHeight, null); + FastBitmapDrawable preview = getWidgetPreview(info, cellSpans[0], cellSpans[1], + cellWidth, cellHeight); + widget.applyFromAppWidgetProviderInfo(info, preview, -1, cellSpans, null, false); + widget.setTag(createItemInfo); + } else if (rawInfo instanceof ResolveInfo) { + // Fill in the shortcuts information + ResolveInfo info = (ResolveInfo) rawInfo; + createItemInfo = new PendingAddItemInfo(); + createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; + createItemInfo.componentName = new ComponentName(info.activityInfo.packageName, + info.activityInfo.name); + FastBitmapDrawable preview = getShortcutPreview(info, cellWidth, cellHeight); + widget.applyFromResolveInfo(mPackageManager, info, preview, null, false); + widget.setTag(createItemInfo); + } widget.setOnClickListener(this); widget.setOnLongClickListener(this); widget.setOnTouchListener(this); @@ -757,13 +844,20 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen dumpAppWidgetProviderInfoList(LOG_TAG, "mWidgets", mWidgets); } private void dumpAppWidgetProviderInfoList(String tag, String label, - List list) { + List list) { Log.d(tag, label + " size=" + list.size()); - for (AppWidgetProviderInfo info: list) { - Log.d(tag, " label=\"" + info.label + "\" previewImage=" + info.previewImage - + " resizeMode=" + info.resizeMode + " configure=" + info.configure - + " initialLayout=" + info.initialLayout - + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight); + for (Object i: list) { + if (i instanceof AppWidgetProviderInfo) { + AppWidgetProviderInfo info = (AppWidgetProviderInfo) i; + Log.d(tag, " label=\"" + info.label + "\" previewImage=" + info.previewImage + + " resizeMode=" + info.resizeMode + " configure=" + info.configure + + " initialLayout=" + info.initialLayout + + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight); + } else if (i instanceof ResolveInfo) { + ResolveInfo info = (ResolveInfo) i; + Log.d(tag, " label=\"" + info.loadLabel(mPackageManager) + "\" icon=" + + info.icon); + } } } @Override diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java index a92e33e9d..72e0962aa 100644 --- a/src/com/android/launcher2/LauncherModel.java +++ b/src/com/android/launcher2/LauncherModel.java @@ -1706,6 +1706,26 @@ public class LauncherModel extends BroadcastReceiver { return sCollator.compare(labelA, labelB); } }; + public static class WidgetAndShortcutNameComparator implements Comparator { + private PackageManager mPackageManager; + private HashMap mLabelCache; + WidgetAndShortcutNameComparator(PackageManager pm) { + mPackageManager = pm; + mLabelCache = new HashMap(); + } + public final int compare(Object a, Object b) { + String labelA, labelB; + if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a); + else labelA = (a instanceof AppWidgetProviderInfo) ? + ((AppWidgetProviderInfo) a).label : + ((ResolveInfo) a).loadLabel(mPackageManager).toString(); + if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b); + else labelB = (b instanceof AppWidgetProviderInfo) ? + ((AppWidgetProviderInfo) b).label : + ((ResolveInfo) b).loadLabel(mPackageManager).toString(); + return sCollator.compare(labelA, labelB); + } + }; public void dumpState() { Log.d(TAG, "mCallbacks=" + mCallbacks); diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java index 14ac9aee1..88c553757 100644 --- a/src/com/android/launcher2/PagedViewWidget.java +++ b/src/com/android/launcher2/PagedViewWidget.java @@ -200,6 +200,26 @@ public class PagedViewWidget extends LinearLayout implements Checkable { } } + public void applyFromResolveInfo(PackageManager pm, ResolveInfo info, + FastBitmapDrawable preview, PagedViewIconCache cache, boolean createHolographicOutline){ + final ImageView image = (ImageView) findViewById(R.id.widget_preview); + image.setImageDrawable(preview); + mPreviewImageView = image; + final TextView name = (TextView) findViewById(R.id.widget_name); + name.setText(info.loadLabel(pm)); + name.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + final TextView dims = (TextView) findViewById(R.id.widget_dims); + dims.setText(mContext.getString(R.string.widget_dims_format, 1, 1)); + dims.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + + if (createHolographicOutline) { + mIconCache = cache; + mIconCacheKey = new PagedViewIconCache.Key(info); + mHolographicOutline = mIconCache.getOutline(mIconCacheKey); + mPreview = preview; + } + } + public void applyFromWallpaperInfo(ResolveInfo info, PackageManager packageManager, FastBitmapDrawable preview, int maxWidth, PagedViewIconCache cache, boolean createHolographicOutline) { -- cgit v1.2.3