fetch and update shortcut icons in background thread
Bug: 141568904
Test: Manually verified use cases from following call-site (with and
without delay)
LauncherAppsCompatVO
1. (Custom Shortcut) Long click on google maps -> widgets ->
drag driving mode to workspace.
2. Open chrome -> add to home screen -> add -> add automatically.
InstallShortcutReceiver
Removed the line that trigger above flow for android O and above,
then open chrome -> add to home screen -> add -> add automatically.
ShortcutDragPreviewProvider
qdb -> long press on suggested app that has deep shortcut -> drag
to workspace.
Change-Id: I59a4d004913a8df697af1fcfe0a080b6da01eefd
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.ShortcutUtil.fetchAndUpdateShortcutIconAsync;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
@@ -482,9 +483,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
return Pair.create(si, null);
|
||||
} else if (shortcutInfo != null) {
|
||||
WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, mContext);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
itemInfo.applyFrom(li.createShortcutIcon(shortcutInfo));
|
||||
li.recycle();
|
||||
fetchAndUpdateShortcutIconAsync(mContext, itemInfo, shortcutInfo, true);
|
||||
return Pair.create(itemInfo, shortcutInfo);
|
||||
} else if (providerInfo != null) {
|
||||
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.graphics.Bitmap;
|
||||
import android.os.Process;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
@@ -32,7 +33,6 @@ import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.icons.cache.BaseIconCache;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
@@ -114,23 +114,37 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
|
||||
}
|
||||
|
||||
// below methods should also migrate to BaseIconFactory
|
||||
|
||||
@WorkerThread
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo) {
|
||||
return createShortcutIcon(shortcutInfo, true /* badged */);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged) {
|
||||
return createShortcutIcon(shortcutInfo, badged, null);
|
||||
}
|
||||
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo,
|
||||
boolean badged, @Nullable Supplier<ItemInfoWithIcon> fallbackIconProvider) {
|
||||
@WorkerThread
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged,
|
||||
@Nullable Supplier<ItemInfoWithIcon> fallbackIconProvider) {
|
||||
return createShortcutIcon(shortcutInfo, badged, true, fallbackIconProvider);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged,
|
||||
boolean useCache, @Nullable Supplier<ItemInfoWithIcon> fallbackIconProvider) {
|
||||
IconCache cache = LauncherAppState.getInstance(mContext).getIconCache();
|
||||
BaseIconCache.CacheEntry entry = cache.getDeepShortcutTitleAndIcon(shortcutInfo);
|
||||
final BitmapInfo bitmapInfo;
|
||||
if (useCache) {
|
||||
bitmapInfo = cache.getDeepShortcutTitleAndIcon(shortcutInfo);
|
||||
} else {
|
||||
bitmapInfo = new BitmapInfo();
|
||||
new ShortcutCachingLogic().loadIcon(mContext, shortcutInfo, bitmapInfo);
|
||||
}
|
||||
|
||||
final Bitmap unbadgedBitmap;
|
||||
if (entry.icon != null) {
|
||||
unbadgedBitmap = entry.icon;
|
||||
if (bitmapInfo.icon != null) {
|
||||
unbadgedBitmap = bitmapInfo.icon;
|
||||
} else {
|
||||
if (fallbackIconProvider != null) {
|
||||
// Fallback icons are already badged and with appropriate shadow
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.launcher3.pm;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.ShortcutUtil.fetchAndUpdateShortcutIconAsync;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
@@ -29,9 +30,7 @@ import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
|
||||
public class PinRequestHelper {
|
||||
|
||||
@@ -81,11 +80,7 @@ public class PinRequestHelper {
|
||||
ShortcutInfo si = request.getShortcutInfo();
|
||||
WorkspaceItemInfo info = new WorkspaceItemInfo(si, context);
|
||||
// Apply the unbadged icon and fetch the actual icon asynchronously.
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
info.applyFrom(li.createShortcutIcon(si, false /* badged */));
|
||||
li.recycle();
|
||||
LauncherAppState.getInstance(context).getModel()
|
||||
.updateAndBindWorkspaceItem(info, si);
|
||||
fetchAndUpdateShortcutIconAsync(context, info, si, false);
|
||||
return info;
|
||||
} else {
|
||||
return null;
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.view.View;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
|
||||
/**
|
||||
* Extension of {@link DragPreviewProvider} which generates bitmaps scaled to the default icon size.
|
||||
@@ -39,22 +40,22 @@ public class ShortcutDragPreviewProvider extends DragPreviewProvider {
|
||||
mPositionShift = shift;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap createDragBitmap() {
|
||||
int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx;
|
||||
return BitmapRenderer.createHardwareBitmap(
|
||||
size + blurSizeOutline,
|
||||
size + blurSizeOutline,
|
||||
(c) -> drawDragViewOnBackground(c, size));
|
||||
}
|
||||
|
||||
private void drawDragViewOnBackground(Canvas canvas, float size) {
|
||||
Drawable d = mView.getBackground();
|
||||
Rect bounds = getDrawableBounds(d);
|
||||
|
||||
int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx;
|
||||
final Bitmap b = Bitmap.createBitmap(
|
||||
size + blurSizeOutline,
|
||||
size + blurSizeOutline,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas canvas = new Canvas(b);
|
||||
canvas.translate(blurSizeOutline / 2, blurSizeOutline / 2);
|
||||
canvas.scale(((float) size) / bounds.width(), ((float) size) / bounds.height(), 0, 0);
|
||||
canvas.scale(size / bounds.width(), size / bounds.height(), 0, 0);
|
||||
canvas.translate(bounds.left, bounds.top);
|
||||
d.draw(canvas);
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,10 +15,20 @@
|
||||
*/
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
|
||||
@@ -61,6 +71,26 @@ public class ShortcutUtil {
|
||||
&& info instanceof WorkspaceItemInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the shortcut icon in background, then update the UI.
|
||||
*/
|
||||
public static void fetchAndUpdateShortcutIconAsync(
|
||||
@NonNull Context context, @NonNull WorkspaceItemInfo info, @NonNull ShortcutInfo si,
|
||||
boolean badged) {
|
||||
if (info.iconBitmap == null) {
|
||||
// use low res icon as placeholder while the actual icon is being fetched.
|
||||
info.iconBitmap = BitmapInfo.LOW_RES_ICON;
|
||||
info.iconColor = Themes.getColorAccent(context);
|
||||
}
|
||||
MODEL_EXECUTOR.execute(() -> {
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
BitmapInfo bitmapInfo = li.createShortcutIcon(si, badged, true, null);
|
||||
info.applyFrom(bitmapInfo);
|
||||
li.recycle();
|
||||
LauncherAppState.getInstance(context).getModel().updateAndBindWorkspaceItem(info, si);
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isActive(ItemInfo info) {
|
||||
boolean isLoading = info instanceof WorkspaceItemInfo
|
||||
&& ((WorkspaceItemInfo) info).hasPromiseIconUi();
|
||||
|
||||
Reference in New Issue
Block a user