Moving icon generation out of ShortcutInfo constructor so that it

can be created on the UI thread

Change-Id: If84e52041eb4ab20807f5cfd4b7f31d7b5f381ed
This commit is contained in:
Sunny Goyal 2017-01-18 11:30:23 -08:00
parent a3db1fc674
commit 1b0726359b
8 changed files with 92 additions and 85 deletions

View File

@ -457,7 +457,9 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
} }
return si; return si;
} else if (shortcutInfo != null) { } else if (shortcutInfo != null) {
return new ShortcutInfo(shortcutInfo, mContext); ShortcutInfo si = new ShortcutInfo(shortcutInfo, mContext);
si.iconBitmap = LauncherIcons.createShortcutIcon(shortcutInfo, mContext);
return si;
} else if (providerInfo != null) { } else if (providerInfo != null) {
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
.fromProviderInfo(mContext, providerInfo); .fromProviderInfo(mContext, providerInfo);

View File

@ -49,6 +49,7 @@ import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.dynamicui.ExtractionUtils; import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.logging.FileLog; import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.AddWorkspaceItemsTask; import com.android.launcher3.model.AddWorkspaceItemsTask;
import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel;
@ -1330,6 +1331,8 @@ public class LauncherModel extends BroadcastReceiver
continue; continue;
} }
info = new ShortcutInfo(pinnedShortcut, context); info = new ShortcutInfo(pinnedShortcut, context);
info.iconBitmap = LauncherIcons
.createShortcutIcon(pinnedShortcut, context);
intent = info.intent; intent = info.intent;
} else { } else {
// Create a shortcut info in disabled mode for now. // Create a shortcut info in disabled mode for now.
@ -2201,6 +2204,17 @@ public class LauncherModel extends BroadcastReceiver
} }
} }
public void updateAndBindShortcutInfo(final ShortcutInfo si, final ShortcutInfoCompat info) {
updateAndBindShortcutInfo(new Provider<ShortcutInfo>() {
@Override
public ShortcutInfo get() {
si.updateFromDeepShortcutInfo(info, mApp.getContext());
si.iconBitmap = LauncherIcons.createShortcutIcon(info, mApp.getContext());
return si;
}
});
}
/** /**
* Utility method to update a shortcut on the background thread. * Utility method to update a shortcut on the background thread.
*/ */

View File

@ -17,21 +17,13 @@
package com.android.launcher3; package com.android.launcher3;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.ContentWriter;
@ -225,42 +217,6 @@ public class ShortcutInfo extends ItemInfoWithIcon {
isDisabled |= FLAG_DISABLED_BY_PUBLISHER; isDisabled |= FLAG_DISABLED_BY_PUBLISHER;
} }
disabledMessage = shortcutInfo.getDisabledMessage(); disabledMessage = shortcutInfo.getDisabledMessage();
// TODO: Use cache for this
LauncherAppState launcherAppState = LauncherAppState.getInstance(context);
Drawable unbadgedDrawable = DeepShortcutManager.getInstance(context)
.getShortcutIconDrawable(shortcutInfo,
launcherAppState.getInvariantDeviceProfile().fillResIconDpi);
IconCache cache = launcherAppState.getIconCache();
Bitmap unbadgedBitmap = unbadgedDrawable == null
? cache.getDefaultIcon(Process.myUserHandle())
: LauncherIcons.createScaledBitmapWithoutShadow(unbadgedDrawable, context);
iconBitmap = getBadgedIcon(unbadgedBitmap, shortcutInfo, cache, context);
}
protected Bitmap getBadgedIcon(Bitmap unbadgedBitmap, ShortcutInfoCompat shortcutInfo,
IconCache cache, Context context) {
unbadgedBitmap = LauncherIcons.addShadowToIcon(unbadgedBitmap, context);
final Bitmap badgeBitmap;
ComponentName cn = shortcutInfo.getActivity();
if (cn != null) {
// Get the app info for the source activity.
AppInfo appInfo = new AppInfo();
appInfo.user = user;
appInfo.componentName = cn;
appInfo.intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setComponent(cn);
cache.getTitleAndIcon(appInfo, false);
badgeBitmap = appInfo.iconBitmap;
} else {
PackageItemInfo pkgInfo = new PackageItemInfo(shortcutInfo.getPackage());
cache.getTitleAndIconForApp(pkgInfo, false);
badgeBitmap = pkgInfo.iconBitmap;
}
return LauncherIcons.badgeWithBitmap(unbadgedBitmap, badgeBitmap, context);
} }
/** Returns the ShortcutInfo id associated with the deep shortcut. */ /** Returns the ShortcutInfo id associated with the deep shortcut. */

View File

@ -16,7 +16,9 @@
package com.android.launcher3.graphics; package com.android.launcher3.graphics;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource; import android.content.Intent.ShortcutIconResource;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
@ -32,11 +34,16 @@ import android.graphics.drawable.PaintDrawable;
import android.os.Process; import android.os.Process;
import android.os.UserHandle; import android.os.UserHandle;
import com.android.launcher3.AppInfo;
import com.android.launcher3.IconCache;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.ProviderConfig; import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -230,6 +237,46 @@ public class LauncherIcons {
} }
} }
public static Bitmap createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context) {
return createShortcutIcon(shortcutInfo, context, true /* badged */);
}
public static Bitmap createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context,
boolean badged) {
LauncherAppState app = LauncherAppState.getInstance(context);
Drawable unbadgedDrawable = DeepShortcutManager.getInstance(context)
.getShortcutIconDrawable(shortcutInfo,
app.getInvariantDeviceProfile().fillResIconDpi);
IconCache cache = app.getIconCache();
Bitmap unbadgedBitmap = unbadgedDrawable == null
? cache.getDefaultIcon(Process.myUserHandle())
: LauncherIcons.createScaledBitmapWithoutShadow(unbadgedDrawable, context);
if (!badged) {
return unbadgedBitmap;
}
unbadgedBitmap = LauncherIcons.addShadowToIcon(unbadgedBitmap, context);
final Bitmap badgeBitmap;
ComponentName cn = shortcutInfo.getActivity();
if (cn != null) {
// Get the app info for the source activity.
AppInfo appInfo = new AppInfo();
appInfo.user = shortcutInfo.getUserHandle();
appInfo.componentName = cn;
appInfo.intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setComponent(cn);
cache.getTitleAndIcon(appInfo, false);
badgeBitmap = appInfo.iconBitmap;
} else {
PackageItemInfo pkgInfo = new PackageItemInfo(shortcutInfo.getPackage());
cache.getTitleAndIconForApp(pkgInfo, false);
badgeBitmap = pkgInfo.iconBitmap;
}
return badgeWithBitmap(unbadgedBitmap, badgeBitmap, context);
}
/** /**
* An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size. * An extension of {@link BitmapDrawable} which returns the bitmap pixel size as intrinsic size.
* This allows the badging to be done based on the action bitmap size rather than * This allows the badging to be done based on the action bitmap size rather than

View File

@ -24,6 +24,7 @@ import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo; import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.MultiHashMap;
@ -87,6 +88,8 @@ public class ShortcutsChangedTask extends ExtendedModelTask {
} }
for (ShortcutInfo shortcutInfo : shortcutInfos) { for (ShortcutInfo shortcutInfo : shortcutInfos) {
shortcutInfo.updateFromDeepShortcutInfo(fullDetails, context); shortcutInfo.updateFromDeepShortcutInfo(fullDetails, context);
shortcutInfo.iconBitmap =
LauncherIcons.createShortcutIcon(fullDetails, context);
updatedShortcutInfos.add(shortcutInfo); updatedShortcutInfos.add(shortcutInfo);
} }
} }

View File

@ -25,6 +25,7 @@ import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo; import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutKey;
@ -85,6 +86,7 @@ public class UserLockStateChangedTask extends ExtendedModelTask {
} }
si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_LOCKED_USER; si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_LOCKED_USER;
si.updateFromDeepShortcutInfo(shortcut, context); si.updateFromDeepShortcutInfo(shortcut, context);
si.iconBitmap = LauncherIcons.createShortcutIcon(shortcut, context);
} else { } else {
si.isDisabled |= ShortcutInfo.FLAG_DISABLED_LOCKED_USER; si.isDisabled |= ShortcutInfo.FLAG_DISABLED_LOCKED_USER;
} }

View File

@ -31,10 +31,8 @@ import com.android.launcher3.LogAccelerateInterpolator;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo; import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.shortcuts.DeepShortcutsContainer.UnbadgedShortcutInfo;
import com.android.launcher3.util.PillRevealOutlineProvider; import com.android.launcher3.util.PillRevealOutlineProvider;
import com.android.launcher3.util.PillWidthRevealOutlineProvider; import com.android.launcher3.util.PillWidthRevealOutlineProvider;
import com.android.launcher3.util.Provider;
/** /**
* A {@link android.widget.FrameLayout} that contains a {@link DeepShortcutView}. * A {@link android.widget.FrameLayout} that contains a {@link DeepShortcutView}.
@ -50,7 +48,8 @@ public class DeepShortcutView extends FrameLayout implements ValueAnimator.Anima
private View mIconView; private View mIconView;
private float mOpenAnimationProgress; private float mOpenAnimationProgress;
private UnbadgedShortcutInfo mInfo; private ShortcutInfo mInfo;
private ShortcutInfoCompat mDetail;
public DeepShortcutView(Context context) { public DeepShortcutView(Context context) {
this(context, null, 0); this(context, null, 0);
@ -92,18 +91,20 @@ public class DeepShortcutView extends FrameLayout implements ValueAnimator.Anima
} }
/** package private **/ /** package private **/
void applyShortcutInfo(UnbadgedShortcutInfo info, DeepShortcutsContainer container) { void applyShortcutInfo(ShortcutInfo info, ShortcutInfoCompat detail,
DeepShortcutsContainer container) {
mInfo = info; mInfo = info;
mDetail = detail;
mBubbleText.applyFromShortcutInfo(info); mBubbleText.applyFromShortcutInfo(info);
mIconView.setBackground(mBubbleText.getIcon()); mIconView.setBackground(mBubbleText.getIcon());
// Use the long label as long as it exists and fits. // Use the long label as long as it exists and fits.
CharSequence longLabel = info.mDetail.getLongLabel(); CharSequence longLabel = mDetail.getLongLabel();
int availableWidth = mBubbleText.getWidth() - mBubbleText.getTotalPaddingLeft() int availableWidth = mBubbleText.getWidth() - mBubbleText.getTotalPaddingLeft()
- mBubbleText.getTotalPaddingRight(); - mBubbleText.getTotalPaddingRight();
boolean usingLongLabel = !TextUtils.isEmpty(longLabel) boolean usingLongLabel = !TextUtils.isEmpty(longLabel)
&& mBubbleText.getPaint().measureText(longLabel.toString()) <= availableWidth; && mBubbleText.getPaint().measureText(longLabel.toString()) <= availableWidth;
mBubbleText.setText(usingLongLabel ? longLabel : info.mDetail.getShortLabel()); mBubbleText.setText(usingLongLabel ? longLabel : mDetail.getShortLabel());
// TODO: Add the click handler to this view directly and not the child view. // TODO: Add the click handler to this view directly and not the child view.
mBubbleText.setOnClickListener(Launcher.getLauncher(getContext())); mBubbleText.setOnClickListener(Launcher.getLauncher(getContext()));
@ -118,14 +119,8 @@ public class DeepShortcutView extends FrameLayout implements ValueAnimator.Anima
final ShortcutInfo badged = new ShortcutInfo(mInfo); final ShortcutInfo badged = new ShortcutInfo(mInfo);
// Queue an update task on the worker thread. This ensures that the badged // Queue an update task on the worker thread. This ensures that the badged
// shortcut eventually gets its icon updated. // shortcut eventually gets its icon updated.
Launcher.getLauncher(getContext()).getModel().updateAndBindShortcutInfo( Launcher.getLauncher(getContext()).getModel()
new Provider<ShortcutInfo>() { .updateAndBindShortcutInfo(badged, mDetail);
@Override
public ShortcutInfo get() {
badged.updateFromDeepShortcutInfo(mInfo.mDetail, getContext());
return badged;
}
});
return badged; return badged;
} }

View File

@ -25,7 +25,6 @@ import android.annotation.TargetApi;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.PointF; import android.graphics.PointF;
@ -49,7 +48,6 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView; import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DragSource; import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget; import com.android.launcher3.DropTarget;
import com.android.launcher3.IconCache;
import com.android.launcher3.ItemInfo; import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.LauncherAnimUtils;
@ -65,6 +63,7 @@ import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.graphics.TriangleShape; import com.android.launcher3.graphics.TriangleShape;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
@ -174,8 +173,11 @@ public class DeepShortcutsContainer extends AbstractFloatingView
} }
for (int i = 0; i < shortcuts.size(); i++) { for (int i = 0; i < shortcuts.size(); i++) {
final ShortcutInfoCompat shortcut = shortcuts.get(i); final ShortcutInfoCompat shortcut = shortcuts.get(i);
uiHandler.post(new UpdateShortcutChild( ShortcutInfo si = new ShortcutInfo(shortcut, mLauncher);
i, new UnbadgedShortcutInfo(shortcut, mLauncher))); // Use unbadged icon for the menu.
si.iconBitmap = LauncherIcons.createShortcutIcon(
shortcut, mLauncher, false /* badged */);
uiHandler.post(new UpdateShortcutChild(i, si, shortcut));
} }
} }
}); });
@ -183,18 +185,22 @@ public class DeepShortcutsContainer extends AbstractFloatingView
/** Updates the child of this container at the given index based on the given shortcut info. */ /** Updates the child of this container at the given index based on the given shortcut info. */
private class UpdateShortcutChild implements Runnable { private class UpdateShortcutChild implements Runnable {
private int mShortcutChildIndex; private final int mShortcutChildIndex;
private UnbadgedShortcutInfo mShortcutChildInfo; private final ShortcutInfo mShortcutChildInfo;
private final ShortcutInfoCompat mDetail;
public UpdateShortcutChild(int shortcutChildIndex, UnbadgedShortcutInfo shortcutChildInfo) {
public UpdateShortcutChild(int shortcutChildIndex, ShortcutInfo shortcutChildInfo,
ShortcutInfoCompat detail) {
mShortcutChildIndex = shortcutChildIndex; mShortcutChildIndex = shortcutChildIndex;
mShortcutChildInfo = shortcutChildInfo; mShortcutChildInfo = shortcutChildInfo;
mDetail = detail;
} }
@Override @Override
public void run() { public void run() {
getShortcutAt(mShortcutChildIndex) getShortcutAt(mShortcutChildIndex)
.applyShortcutInfo(mShortcutChildInfo, DeepShortcutsContainer.this); .applyShortcutInfo(mShortcutChildInfo, mDetail, DeepShortcutsContainer.this);
} }
} }
@ -676,24 +682,6 @@ public class DeepShortcutsContainer extends AbstractFloatingView
return null; return null;
} }
/**
* Extension of {@link ShortcutInfo} which does not badge the icons.
*/
static class UnbadgedShortcutInfo extends ShortcutInfo {
public final ShortcutInfoCompat mDetail;
public UnbadgedShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) {
super(shortcutInfo, context);
mDetail = shortcutInfo;
}
@Override
protected Bitmap getBadgedIcon(Bitmap unbadgedBitmap, ShortcutInfoCompat shortcutInfo,
IconCache cache, Context context) {
return unbadgedBitmap;
}
}
/** /**
* Returns a DeepShortcutsContainer which is already open or null * Returns a DeepShortcutsContainer which is already open or null
*/ */