Merge "Making LauncherIcons thread safe" into ub-launcher3-master
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<com.android.launcher3.folder.Folder xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/round_rect_primary"
|
||||
android:elevation="5dp"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.android.launcher3.folder.FolderPagedView
|
||||
android:id="@+id/folder_content"
|
||||
android:clipToPadding="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingTop="16dp"
|
||||
launcher:pageIndicator="@+id/folder_page_indicator" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/folder_footer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp" >
|
||||
|
||||
<com.android.launcher3.ExtendedEditText
|
||||
android:id="@+id/folder_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:gravity="center_horizontal"
|
||||
android:hint="@string/folder_hint_text"
|
||||
android:imeOptions="flagNoExtractUi"
|
||||
android:paddingBottom="@dimen/folder_label_padding_bottom"
|
||||
android:paddingTop="@dimen/folder_label_padding_top"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorTertiary"
|
||||
android:includeFontPadding="false"
|
||||
android:textColorHighlight="?android:attr/colorControlHighlight"
|
||||
android:textColorHint="?android:attr/textColorHint"
|
||||
android:textSize="@dimen/folder_label_text_size" />
|
||||
|
||||
<com.android.launcher3.pageindicators.PageIndicatorDots
|
||||
android:id="@+id/folder_page_indicator"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="1dp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.launcher3.folder.Folder>
|
||||
@@ -110,7 +110,7 @@ public class AppInfo extends ItemInfoWithIcon {
|
||||
info.runtimeStatusFlags |= (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
|
||||
? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
|
||||
|
||||
if (FeatureFlags.LEGACY_ICON_TREATMENT && Utilities.ATLEAST_OREO
|
||||
if (Utilities.ATLEAST_OREO
|
||||
&& appInfo.targetSdkVersion >= Build.VERSION_CODES.O
|
||||
&& Process.myUserHandle().equals(lai.getUser())) {
|
||||
// The icon for a non-primary user is badged, hence it's not exactly an adaptive icon.
|
||||
|
||||
@@ -437,9 +437,11 @@ public class AutoInstallsLayout {
|
||||
}
|
||||
|
||||
// Auto installs should always support the current platform version.
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
mValues.put(LauncherSettings.Favorites.ICON, Utilities.flattenBitmap(
|
||||
LauncherIcons.createBadgedIconBitmap(
|
||||
icon, Process.myUserHandle(), mContext, VERSION.SDK_INT).icon));
|
||||
li.createBadgedIconBitmap(icon, Process.myUserHandle(), VERSION.SDK_INT).icon));
|
||||
li.recycle();
|
||||
|
||||
mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
|
||||
mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
|
||||
|
||||
|
||||
@@ -193,8 +193,10 @@ public class IconCache {
|
||||
}
|
||||
|
||||
protected BitmapInfo makeDefaultIcon(UserHandle user) {
|
||||
Drawable unbadged = getFullResDefaultActivityIcon();
|
||||
return LauncherIcons.createBadgedIconBitmap(unbadged, user, mContext, VERSION.SDK_INT);
|
||||
try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
|
||||
return li.createBadgedIconBitmap(
|
||||
getFullResDefaultActivityIcon(), user, VERSION.SDK_INT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,8 +380,10 @@ public class IconCache {
|
||||
}
|
||||
if (entry == null) {
|
||||
entry = new CacheEntry();
|
||||
LauncherIcons.createBadgedIconBitmap(getFullResIcon(app), app.getUser(),
|
||||
mContext, app.getApplicationInfo().targetSdkVersion).applyTo(entry);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
li.createBadgedIconBitmap(getFullResIcon(app), app.getUser(),
|
||||
app.getApplicationInfo().targetSdkVersion).applyTo(entry);
|
||||
li.recycle();
|
||||
}
|
||||
entry.title = app.getLabel();
|
||||
entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser());
|
||||
@@ -535,9 +539,10 @@ public class IconCache {
|
||||
providerFetchedOnce = true;
|
||||
|
||||
if (info != null) {
|
||||
LauncherIcons.createBadgedIconBitmap(
|
||||
getFullResIcon(info), info.getUser(), mContext,
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
li.createBadgedIconBitmap(getFullResIcon(info), info.getUser(),
|
||||
info.getApplicationInfo().targetSdkVersion).applyTo(entry);
|
||||
li.recycle();
|
||||
} else {
|
||||
if (usePackageIcon) {
|
||||
CacheEntry packageEntry = getEntryForPackageLocked(
|
||||
@@ -596,7 +601,9 @@ public class IconCache {
|
||||
entry.title = title;
|
||||
}
|
||||
if (icon != null) {
|
||||
LauncherIcons.createIconBitmap(icon, mContext).applyTo(entry);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
li.createIconBitmap(icon).applyTo(entry);
|
||||
li.recycle();
|
||||
}
|
||||
if (!TextUtils.isEmpty(title) && entry.icon != null) {
|
||||
mCache.put(cacheKey, entry);
|
||||
@@ -633,14 +640,17 @@ public class IconCache {
|
||||
throw new NameNotFoundException("ApplicationInfo is null");
|
||||
}
|
||||
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
// Load the full res icon for the application, but if useLowResIcon is set, then
|
||||
// only keep the low resolution icon instead of the larger full-sized icon
|
||||
BitmapInfo iconInfo = LauncherIcons.createBadgedIconBitmap(
|
||||
appInfo.loadIcon(mPackageManager), user, mContext, appInfo.targetSdkVersion);
|
||||
BitmapInfo iconInfo = li.createBadgedIconBitmap(
|
||||
appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion);
|
||||
if (mInstantAppResolver.isInstantApp(appInfo)) {
|
||||
LauncherIcons.badgeWithDrawable(iconInfo.icon,
|
||||
mContext.getDrawable(R.drawable.ic_instant_app_badge), mContext);
|
||||
li.badgeWithDrawable(iconInfo.icon,
|
||||
mContext.getDrawable(R.drawable.ic_instant_app_badge));
|
||||
}
|
||||
li.recycle();
|
||||
|
||||
Bitmap lowResIcon = generateLowResIcon(iconInfo.icon);
|
||||
entry.title = appInfo.loadLabel(mPackageManager);
|
||||
entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
|
||||
@@ -776,10 +786,7 @@ public class IconCache {
|
||||
}
|
||||
|
||||
private static final class IconDB extends SQLiteCacheHelper {
|
||||
private final static int DB_VERSION = 18;
|
||||
|
||||
private final static int RELEASE_VERSION = DB_VERSION +
|
||||
(FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION ? 0 : 1);
|
||||
private final static int RELEASE_VERSION = 20;
|
||||
|
||||
private final static String TABLE_NAME = "icons";
|
||||
private final static String COLUMN_ROWID = "rowid";
|
||||
|
||||
@@ -498,7 +498,9 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
return Pair.create((ItemInfo) si, (Object) activityInfo);
|
||||
} else if (shortcutInfo != null) {
|
||||
ShortcutInfo si = new ShortcutInfo(shortcutInfo, mContext);
|
||||
LauncherIcons.createShortcutIcon(shortcutInfo, mContext).applyTo(si);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
li.createShortcutIcon(shortcutInfo).applyTo(si);
|
||||
li.recycle();
|
||||
return Pair.create((ItemInfo) si, (Object) shortcutInfo);
|
||||
} else if (providerInfo != null) {
|
||||
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
|
||||
@@ -643,15 +645,18 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
info.user = Process.myUserHandle();
|
||||
|
||||
BitmapInfo iconInfo = null;
|
||||
LauncherIcons li = LauncherIcons.obtain(app.getContext());
|
||||
if (bitmap instanceof Bitmap) {
|
||||
iconInfo = LauncherIcons.createIconBitmap((Bitmap) bitmap, app.getContext());
|
||||
iconInfo = li.createIconBitmap((Bitmap) bitmap);
|
||||
} else {
|
||||
Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
|
||||
if (extra instanceof Intent.ShortcutIconResource) {
|
||||
info.iconResource = (Intent.ShortcutIconResource) extra;
|
||||
iconInfo = LauncherIcons.createIconBitmap(info.iconResource, app.getContext());
|
||||
iconInfo = li.createIconBitmap(info.iconResource);
|
||||
}
|
||||
}
|
||||
li.recycle();
|
||||
|
||||
if (iconInfo == null) {
|
||||
iconInfo = app.getIconCache().getDefaultIcon(info.user);
|
||||
}
|
||||
|
||||
@@ -620,7 +620,9 @@ public class LauncherModel extends BroadcastReceiver
|
||||
@Override
|
||||
public ShortcutInfo get() {
|
||||
si.updateFromDeepShortcutInfo(info, mApp.getContext());
|
||||
LauncherIcons.createShortcutIcon(info, mApp.getContext()).applyTo(si);
|
||||
LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
|
||||
li.createShortcutIcon(info).applyTo(si);
|
||||
li.recycle();
|
||||
return si;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -469,8 +469,11 @@ public class WidgetPreviewLoader {
|
||||
}
|
||||
RectF boxRect = drawBoxWithShadow(c, size, size);
|
||||
|
||||
Bitmap icon = LauncherIcons.createScaledBitmapWithoutShadow(
|
||||
mutateOnMainThread(info.getFullResIcon(mIconCache)), mContext, 0);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
Bitmap icon = li.createScaledBitmapWithoutShadow(
|
||||
mutateOnMainThread(info.getFullResIcon(mIconCache)), 0);
|
||||
li.recycle();
|
||||
|
||||
Rect src = new Rect(0, 0, icon.getWidth(), icon.getHeight());
|
||||
|
||||
boxRect.set(0, 0, iconSize, iconSize);
|
||||
|
||||
@@ -137,7 +137,9 @@ public class LauncherAppsCompatVO extends LauncherAppsCompatVL {
|
||||
ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
|
||||
ShortcutInfo info = new ShortcutInfo(compat, context);
|
||||
// Apply the unbadged icon and fetch the actual icon asynchronously.
|
||||
LauncherIcons.createShortcutIcon(compat, context, false /* badged */).applyTo(info);
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
li.createShortcutIcon(compat, false /* badged */).applyTo(info);
|
||||
li.recycle();
|
||||
LauncherAppState.getInstance(context).getModel()
|
||||
.updateAndBindShortcutInfo(info, compat);
|
||||
return info;
|
||||
|
||||
@@ -31,8 +31,6 @@ abstract class BaseFlags {
|
||||
public static final boolean IS_DOGFOOD_BUILD = false;
|
||||
public static final String AUTHORITY = "com.android.launcher3.settings".intern();
|
||||
|
||||
// Custom flags go below this
|
||||
public static boolean LAUNCHER3_DISABLE_ICON_NORMALIZATION = false;
|
||||
// When enabled allows to use any point on the fast scrollbar to start dragging.
|
||||
public static final boolean LAUNCHER3_DIRECT_SCROLL = true;
|
||||
// When enabled the promise icon is visible in all apps while installation an app.
|
||||
@@ -46,10 +44,6 @@ abstract class BaseFlags {
|
||||
public static final boolean QSB_ON_FIRST_SCREEN = true;
|
||||
// When enabled the all-apps icon is not added to the hotseat.
|
||||
public static final boolean NO_ALL_APPS_ICON = true;
|
||||
// When enabled, icons not supporting {@link AdaptiveIconDrawable} will be wrapped in {@link FixedScaleDrawable}.
|
||||
public static final boolean LEGACY_ICON_TREATMENT = true;
|
||||
// When enabled, adaptive icons would have shadows baked when being stored to icon cache.
|
||||
public static final boolean ADAPTIVE_ICON_SHADOW = true;
|
||||
// When enabled, app discovery will be enabled if service is implemented
|
||||
public static final boolean DISCOVERY_ENABLED = false;
|
||||
|
||||
|
||||
@@ -224,8 +224,10 @@ public class DragView extends View {
|
||||
mBadge = getBadge(info, appState, outObj[0]);
|
||||
mBadge.setBounds(badgeBounds);
|
||||
|
||||
LauncherIcons li = LauncherIcons.obtain(mLauncher);
|
||||
Utilities.scaleRectAboutCenter(bounds,
|
||||
IconNormalizer.getInstance(mLauncher).getScale(dr, null, null, null));
|
||||
li.getNormalizer().getScale(dr, null, null, null));
|
||||
li.recycle();
|
||||
AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr;
|
||||
|
||||
// Shrink very tiny bit so that the clip path is smaller than the original bitmap
|
||||
|
||||
@@ -453,9 +453,8 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
|
||||
*/
|
||||
@SuppressLint("InflateParams")
|
||||
static Folder fromXml(Launcher launcher) {
|
||||
return (Folder) launcher.getLayoutInflater().inflate(
|
||||
FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION
|
||||
? R.layout.user_folder : R.layout.user_folder_icon_normalized, null);
|
||||
return (Folder) launcher.getLayoutInflater()
|
||||
.inflate(R.layout.user_folder_icon_normalized, null);
|
||||
}
|
||||
|
||||
private void startAnimation(final AnimatorSet a) {
|
||||
|
||||
@@ -37,10 +37,7 @@ import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Random;
|
||||
|
||||
public class IconNormalizer {
|
||||
|
||||
@@ -64,9 +61,6 @@ public class IconNormalizer {
|
||||
private static final float PIXEL_DIFF_PERCENTAGE_THRESHOLD = 0.005f;
|
||||
private static final float SCALE_NOT_INITIALIZED = 0;
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static IconNormalizer sIconNormalizer;
|
||||
|
||||
private final int mMaxSize;
|
||||
private final Bitmap mBitmap;
|
||||
private final Bitmap mBitmapARGB;
|
||||
@@ -88,11 +82,8 @@ public class IconNormalizer {
|
||||
private final Paint mPaintIcon;
|
||||
private final Canvas mCanvasARGB;
|
||||
|
||||
private final File mDir;
|
||||
private int mFileId;
|
||||
private final Random mRandom;
|
||||
|
||||
private IconNormalizer(Context context) {
|
||||
/** package private **/
|
||||
IconNormalizer(Context context) {
|
||||
// Use twice the icon size as maximum size to avoid scaling down twice.
|
||||
mMaxSize = LauncherAppState.getIDP(context).iconBitmapSize * 2;
|
||||
mBitmap = Bitmap.createBitmap(mMaxSize, mMaxSize, Bitmap.Config.ALPHA_8);
|
||||
@@ -124,9 +115,6 @@ public class IconNormalizer {
|
||||
|
||||
mMatrix = new Matrix();
|
||||
mAdaptiveIconScale = SCALE_NOT_INITIALIZED;
|
||||
|
||||
mDir = context.getExternalFilesDir(null);
|
||||
mRandom = new Random();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,18 +136,9 @@ public class IconNormalizer {
|
||||
// Condition 2:
|
||||
// Actual icon (white) and the fitted shape (e.g., circle)(red) XOR operation
|
||||
// should generate transparent image, if the actual icon is equivalent to the shape.
|
||||
mFileId = mRandom.nextInt();
|
||||
mBitmapARGB.eraseColor(Color.TRANSPARENT);
|
||||
mCanvasARGB.drawBitmap(mBitmap, 0, 0, mPaintIcon);
|
||||
|
||||
if (DEBUG) {
|
||||
final File beforeFile = new File(mDir, "isShape" + mFileId + "_before.png");
|
||||
try {
|
||||
mBitmapARGB.compress(Bitmap.CompressFormat.PNG, 100,
|
||||
new FileOutputStream(beforeFile));
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
// Fit the shape within the icon's bounding box
|
||||
mMatrix.reset();
|
||||
mMatrix.setScale(mBounds.width(), mBounds.height());
|
||||
@@ -172,24 +151,8 @@ public class IconNormalizer {
|
||||
// DST_OUT operation around the mask path outline
|
||||
mCanvasARGB.drawPath(maskPath, mPaintMaskShapeOutline);
|
||||
|
||||
boolean isTrans = isTransparentBitmap(mBitmapARGB);
|
||||
if (DEBUG) {
|
||||
final File afterFile = new File(mDir,
|
||||
"isShape" + mFileId + "_after_" + isTrans + ".png");
|
||||
try {
|
||||
mBitmapARGB.compress(Bitmap.CompressFormat.PNG, 100,
|
||||
new FileOutputStream(afterFile));
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
// Check if the result is almost transparent
|
||||
if (!isTrans) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Not same as mask shape");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return isTransparentBitmap(mBitmapARGB);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,19 +166,13 @@ public class IconNormalizer {
|
||||
mBounds.left, mBounds.top,
|
||||
w, h);
|
||||
int sum = 0;
|
||||
for (int i = 0; i < w * h; i++) {
|
||||
for (int i = w * h - 1; i >= 0; i--) {
|
||||
if(Color.alpha(mPixelsARGB[i]) > MIN_VISIBLE_ALPHA) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
float percentageDiffPixels = ((float) sum) / (mBounds.width() * mBounds.height());
|
||||
boolean transparentImage = percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"Total # pixel that is different (id=" + mFileId + "):" + percentageDiffPixels
|
||||
+ "=" + sum + "/" + mBounds.width() * mBounds.height());
|
||||
}
|
||||
return transparentImage;
|
||||
return percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,13 +373,4 @@ public class IconNormalizer {
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
|
||||
public static IconNormalizer getInstance(Context context) {
|
||||
synchronized (LOCK) {
|
||||
if (sIconNormalizer == null) {
|
||||
sIconNormalizer = new IconNormalizer(context);
|
||||
}
|
||||
}
|
||||
return sIconNormalizer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
package com.android.launcher3.graphics;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import static android.graphics.Paint.DITHER_FLAG;
|
||||
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
|
||||
|
||||
import static com.android.launcher3.graphics.ShadowGenerator.BLUR_FACTOR;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -25,7 +29,6 @@ import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@@ -41,11 +44,11 @@ import android.support.annotation.Nullable;
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.FastBitmapDrawable;
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutManager;
|
||||
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
|
||||
@@ -56,32 +59,95 @@ import com.android.launcher3.util.Themes;
|
||||
/**
|
||||
* Helper methods for generating various launcher icons
|
||||
*/
|
||||
public class LauncherIcons {
|
||||
public class LauncherIcons implements AutoCloseable {
|
||||
|
||||
private static final Rect sOldBounds = new Rect();
|
||||
private static final Canvas sCanvas = new Canvas();
|
||||
public static final Object sPoolSync = new Object();
|
||||
private static LauncherIcons sPool;
|
||||
|
||||
static {
|
||||
sCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
|
||||
Paint.FILTER_BITMAP_FLAG));
|
||||
/**
|
||||
* Return a new Message instance from the global pool. Allows us to
|
||||
* avoid allocating new objects in many cases.
|
||||
*/
|
||||
public static LauncherIcons obtain(Context context) {
|
||||
synchronized (sPoolSync) {
|
||||
if (sPool != null) {
|
||||
LauncherIcons m = sPool;
|
||||
sPool = m.next;
|
||||
m.next = null;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return new LauncherIcons(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycles a LauncherIcons that may be in-use.
|
||||
*/
|
||||
public void recycle() {
|
||||
synchronized (sPoolSync) {
|
||||
next = sPool;
|
||||
sPool = this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
recycle();
|
||||
}
|
||||
|
||||
private final Rect mOldBounds = new Rect();
|
||||
private final Context mContext;
|
||||
private final Canvas mCanvas;
|
||||
private final PackageManager mPm;
|
||||
|
||||
private final int mFillResIconDpi;
|
||||
private final int mIconBitmapSize;
|
||||
|
||||
private IconNormalizer mNormalizer;
|
||||
private ShadowGenerator mShadowGenerator;
|
||||
|
||||
// sometimes we store linked lists of these things
|
||||
private LauncherIcons next;
|
||||
|
||||
private LauncherIcons(Context context) {
|
||||
mContext = context.getApplicationContext();
|
||||
mPm = mContext.getPackageManager();
|
||||
|
||||
InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext);
|
||||
mFillResIconDpi = idp.fillResIconDpi;
|
||||
mIconBitmapSize = idp.iconBitmapSize;
|
||||
|
||||
mCanvas = new Canvas();
|
||||
mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG));
|
||||
}
|
||||
|
||||
public ShadowGenerator getShadowGenerator() {
|
||||
if (mShadowGenerator == null) {
|
||||
mShadowGenerator = new ShadowGenerator(mContext);
|
||||
}
|
||||
return mShadowGenerator;
|
||||
}
|
||||
|
||||
public IconNormalizer getNormalizer() {
|
||||
if (mNormalizer == null) {
|
||||
mNormalizer = new IconNormalizer(mContext);
|
||||
}
|
||||
return mNormalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bitmap suitable for the all apps view. If the package or the resource do not
|
||||
* exist, it returns null.
|
||||
*/
|
||||
public static BitmapInfo createIconBitmap(ShortcutIconResource iconRes, Context context) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
// the resource
|
||||
public BitmapInfo createIconBitmap(ShortcutIconResource iconRes) {
|
||||
try {
|
||||
Resources resources = packageManager.getResourcesForApplication(iconRes.packageName);
|
||||
Resources resources = mPm.getResourcesForApplication(iconRes.packageName);
|
||||
if (resources != null) {
|
||||
final int id = resources.getIdentifier(iconRes.resourceName, null, null);
|
||||
// do not stamp old legacy shortcuts as the app may have already forgotten about it
|
||||
return createBadgedIconBitmap(resources.getDrawableForDensity(
|
||||
id, LauncherAppState.getIDP(context).fillResIconDpi),
|
||||
return createBadgedIconBitmap(
|
||||
resources.getDrawableForDensity(id, mFillResIconDpi),
|
||||
Process.myUserHandle() /* only available on primary user */,
|
||||
context,
|
||||
0 /* do not apply legacy treatment */);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -93,13 +159,12 @@ public class LauncherIcons {
|
||||
/**
|
||||
* Returns a bitmap which is of the appropriate size to be displayed as an icon
|
||||
*/
|
||||
public static BitmapInfo createIconBitmap(Bitmap icon, Context context) {
|
||||
final int iconBitmapSize = LauncherAppState.getIDP(context).iconBitmapSize;
|
||||
if (iconBitmapSize == icon.getWidth() && iconBitmapSize == icon.getHeight()) {
|
||||
public BitmapInfo createIconBitmap(Bitmap icon) {
|
||||
if (mIconBitmapSize == icon.getWidth() && mIconBitmapSize == icon.getHeight()) {
|
||||
return BitmapInfo.fromBitmap(icon);
|
||||
}
|
||||
return BitmapInfo.fromBitmap(
|
||||
createIconBitmap(new BitmapDrawable(context.getResources(), icon), context, 1f));
|
||||
createIconBitmap(new BitmapDrawable(mContext.getResources(), icon), 1f));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,51 +172,24 @@ public class LauncherIcons {
|
||||
* view or workspace. The icon is badged for {@param user}.
|
||||
* The bitmap is also visually normalized with other icons.
|
||||
*/
|
||||
public static BitmapInfo createBadgedIconBitmap(
|
||||
Drawable icon, UserHandle user, Context context, int iconAppTargetSdk) {
|
||||
|
||||
IconNormalizer normalizer;
|
||||
float scale = 1f;
|
||||
if (!FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION) {
|
||||
normalizer = IconNormalizer.getInstance(context);
|
||||
if (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) {
|
||||
boolean[] outShape = new boolean[1];
|
||||
AdaptiveIconDrawable dr = (AdaptiveIconDrawable)
|
||||
context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate();
|
||||
dr.setBounds(0, 0, 1, 1);
|
||||
scale = normalizer.getScale(icon, null, dr.getIconMask(), outShape);
|
||||
if (FeatureFlags.LEGACY_ICON_TREATMENT &&
|
||||
!outShape[0]){
|
||||
Drawable wrappedIcon = wrapToAdaptiveIconDrawable(context, icon, scale);
|
||||
if (wrappedIcon != icon) {
|
||||
icon = wrappedIcon;
|
||||
scale = normalizer.getScale(icon, null, null, null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scale = normalizer.getScale(icon, null, null, null);
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = createIconBitmap(icon, context, scale);
|
||||
if (FeatureFlags.ADAPTIVE_ICON_SHADOW && Utilities.ATLEAST_OREO &&
|
||||
icon instanceof AdaptiveIconDrawable) {
|
||||
synchronized (sCanvas) {
|
||||
sCanvas.setBitmap(bitmap);
|
||||
ShadowGenerator.getInstance(context).recreateIcon(
|
||||
Bitmap.createBitmap(bitmap), sCanvas);
|
||||
sCanvas.setBitmap(null);
|
||||
}
|
||||
public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk) {
|
||||
float[] scale = new float[1];
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, iconAppTargetSdk, null, scale);
|
||||
Bitmap bitmap = createIconBitmap(icon, scale[0]);
|
||||
if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
mCanvas.setBitmap(bitmap);
|
||||
getShadowGenerator().recreateIcon(Bitmap.createBitmap(bitmap), mCanvas);
|
||||
mCanvas.setBitmap(null);
|
||||
}
|
||||
|
||||
final Bitmap result;
|
||||
if (user != null && !Process.myUserHandle().equals(user)) {
|
||||
BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
|
||||
Drawable badged = context.getPackageManager().getUserBadgedIcon(
|
||||
drawable, user);
|
||||
Drawable badged = mPm.getUserBadgedIcon(drawable, user);
|
||||
if (badged instanceof BitmapDrawable) {
|
||||
result = ((BitmapDrawable) badged).getBitmap();
|
||||
} else {
|
||||
result = createIconBitmap(badged, context, 1f);
|
||||
result = createIconBitmap(badged, 1f);
|
||||
}
|
||||
} else {
|
||||
result = bitmap;
|
||||
@@ -163,170 +201,134 @@ public class LauncherIcons {
|
||||
* Creates a normalized bitmap suitable for the all apps view. The bitmap is also visually
|
||||
* normalized with other icons and has enough spacing to add shadow.
|
||||
*/
|
||||
public static Bitmap createScaledBitmapWithoutShadow(
|
||||
Drawable icon, Context context, int iconAppTargetSdk) {
|
||||
public Bitmap createScaledBitmapWithoutShadow(Drawable icon, int iconAppTargetSdk) {
|
||||
RectF iconBounds = new RectF();
|
||||
IconNormalizer normalizer;
|
||||
float[] scale = new float[1];
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, iconAppTargetSdk, iconBounds, scale);
|
||||
return createIconBitmap(icon,
|
||||
Math.min(scale[0], ShadowGenerator.getScaleForBounds(iconBounds)));
|
||||
}
|
||||
|
||||
private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, int iconAppTargetSdk,
|
||||
RectF outIconBounds, float[] outScale) {
|
||||
float scale = 1f;
|
||||
if (!FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION) {
|
||||
normalizer = IconNormalizer.getInstance(context);
|
||||
if (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) {
|
||||
boolean[] outShape = new boolean[1];
|
||||
AdaptiveIconDrawable dr = (AdaptiveIconDrawable)
|
||||
context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate();
|
||||
dr.setBounds(0, 0, 1, 1);
|
||||
scale = normalizer.getScale(icon, iconBounds, dr.getIconMask(), outShape);
|
||||
if (Utilities.ATLEAST_OREO && FeatureFlags.LEGACY_ICON_TREATMENT &&
|
||||
!outShape[0]) {
|
||||
Drawable wrappedIcon = wrapToAdaptiveIconDrawable(context, icon, scale);
|
||||
if (wrappedIcon != icon) {
|
||||
icon = wrappedIcon;
|
||||
scale = normalizer.getScale(icon, iconBounds, null, null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scale = normalizer.getScale(icon, iconBounds, null, null);
|
||||
if (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) {
|
||||
boolean[] outShape = new boolean[1];
|
||||
AdaptiveIconDrawable dr = (AdaptiveIconDrawable)
|
||||
mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate();
|
||||
dr.setBounds(0, 0, 1, 1);
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
|
||||
if (Utilities.ATLEAST_OREO && !outShape[0] && !(icon instanceof AdaptiveIconDrawable)) {
|
||||
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
|
||||
fsd.setDrawable(icon);
|
||||
fsd.setScale(scale);
|
||||
icon = dr;
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
}
|
||||
|
||||
} else {
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
}
|
||||
scale = Math.min(scale, ShadowGenerator.getScaleForBounds(iconBounds));
|
||||
return createIconBitmap(icon, context, scale);
|
||||
|
||||
outScale[0] = scale;
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
|
||||
*/
|
||||
public static void badgeWithDrawable(Bitmap target, Drawable badge, Context context) {
|
||||
synchronized (sCanvas) {
|
||||
sCanvas.setBitmap(target);
|
||||
badgeWithDrawable(sCanvas, badge, context);
|
||||
sCanvas.setBitmap(null);
|
||||
}
|
||||
public void badgeWithDrawable(Bitmap target, Drawable badge) {
|
||||
mCanvas.setBitmap(target);
|
||||
badgeWithDrawable(mCanvas, badge);
|
||||
mCanvas.setBitmap(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the {@param badge} on top of {@param target} using the badge dimensions.
|
||||
*/
|
||||
private static void badgeWithDrawable(Canvas target, Drawable badge, Context context) {
|
||||
int badgeSize = context.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
|
||||
int iconSize = LauncherAppState.getIDP(context).iconBitmapSize;
|
||||
badge.setBounds(iconSize - badgeSize, iconSize - badgeSize, iconSize, iconSize);
|
||||
private void badgeWithDrawable(Canvas target, Drawable badge) {
|
||||
int badgeSize = mContext.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
|
||||
badge.setBounds(mIconBitmapSize - badgeSize, mIconBitmapSize - badgeSize,
|
||||
mIconBitmapSize, mIconBitmapSize);
|
||||
badge.draw(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scale the scale to apply before drawing {@param icon} on the canvas
|
||||
*/
|
||||
private static Bitmap createIconBitmap(Drawable icon, Context context, float scale) {
|
||||
synchronized (sCanvas) {
|
||||
final int iconBitmapSize = LauncherAppState.getIDP(context).iconBitmapSize;
|
||||
int width = iconBitmapSize;
|
||||
int height = iconBitmapSize;
|
||||
private Bitmap createIconBitmap(Drawable icon, float scale) {
|
||||
int width = mIconBitmapSize;
|
||||
int height = mIconBitmapSize;
|
||||
|
||||
if (icon instanceof PaintDrawable) {
|
||||
PaintDrawable painter = (PaintDrawable) icon;
|
||||
painter.setIntrinsicWidth(width);
|
||||
painter.setIntrinsicHeight(height);
|
||||
} else if (icon instanceof BitmapDrawable) {
|
||||
// Ensure the bitmap has a density.
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
|
||||
Bitmap bitmap = bitmapDrawable.getBitmap();
|
||||
if (bitmap != null && bitmap.getDensity() == Bitmap.DENSITY_NONE) {
|
||||
bitmapDrawable.setTargetDensity(context.getResources().getDisplayMetrics());
|
||||
}
|
||||
if (icon instanceof PaintDrawable) {
|
||||
PaintDrawable painter = (PaintDrawable) icon;
|
||||
painter.setIntrinsicWidth(width);
|
||||
painter.setIntrinsicHeight(height);
|
||||
} else if (icon instanceof BitmapDrawable) {
|
||||
// Ensure the bitmap has a density.
|
||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
|
||||
Bitmap bitmap = bitmapDrawable.getBitmap();
|
||||
if (bitmap != null && bitmap.getDensity() == Bitmap.DENSITY_NONE) {
|
||||
bitmapDrawable.setTargetDensity(mContext.getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
int sourceWidth = icon.getIntrinsicWidth();
|
||||
int sourceHeight = icon.getIntrinsicHeight();
|
||||
if (sourceWidth > 0 && sourceHeight > 0) {
|
||||
// Scale the icon proportionally to the icon dimensions
|
||||
final float ratio = (float) sourceWidth / sourceHeight;
|
||||
if (sourceWidth > sourceHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (sourceHeight > sourceWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
}
|
||||
// no intrinsic size --> use default size
|
||||
int textureWidth = iconBitmapSize;
|
||||
int textureHeight = iconBitmapSize;
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
final Canvas canvas = sCanvas;
|
||||
canvas.setBitmap(bitmap);
|
||||
|
||||
final int left = (textureWidth-width) / 2;
|
||||
final int top = (textureHeight-height) / 2;
|
||||
|
||||
sOldBounds.set(icon.getBounds());
|
||||
if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
int offset = Math.max((int)(ShadowGenerator.BLUR_FACTOR * iconBitmapSize),
|
||||
Math.min(left, top));
|
||||
int size = Math.max(width, height);
|
||||
icon.setBounds(offset, offset, size, size);
|
||||
} else {
|
||||
icon.setBounds(left, top, left+width, top+height);
|
||||
}
|
||||
canvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
canvas.scale(scale, scale, textureWidth / 2, textureHeight / 2);
|
||||
icon.draw(canvas);
|
||||
canvas.restore();
|
||||
icon.setBounds(sOldBounds);
|
||||
canvas.setBitmap(null);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the platform is running O but the app is not providing AdaptiveIconDrawable, then
|
||||
* shrink the legacy icon and set it as foreground. Use color drawable as background to
|
||||
* create AdaptiveIconDrawable.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
private static Drawable wrapToAdaptiveIconDrawable(
|
||||
Context context, Drawable drawable, float scale) {
|
||||
if (!(FeatureFlags.LEGACY_ICON_TREATMENT && Utilities.ATLEAST_OREO)) {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!(drawable instanceof AdaptiveIconDrawable)) {
|
||||
AdaptiveIconDrawable iconWrapper = (AdaptiveIconDrawable)
|
||||
context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate();
|
||||
FixedScaleDrawable fsd = ((FixedScaleDrawable) iconWrapper.getForeground());
|
||||
fsd.setDrawable(drawable);
|
||||
fsd.setScale(scale);
|
||||
return iconWrapper;
|
||||
int sourceWidth = icon.getIntrinsicWidth();
|
||||
int sourceHeight = icon.getIntrinsicHeight();
|
||||
if (sourceWidth > 0 && sourceHeight > 0) {
|
||||
// Scale the icon proportionally to the icon dimensions
|
||||
final float ratio = (float) sourceWidth / sourceHeight;
|
||||
if (sourceWidth > sourceHeight) {
|
||||
height = (int) (width / ratio);
|
||||
} else if (sourceHeight > sourceWidth) {
|
||||
width = (int) (height * ratio);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return drawable;
|
||||
}
|
||||
return drawable;
|
||||
// no intrinsic size --> use default size
|
||||
int textureWidth = mIconBitmapSize;
|
||||
int textureHeight = mIconBitmapSize;
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
mCanvas.setBitmap(bitmap);
|
||||
|
||||
final int left = (textureWidth-width) / 2;
|
||||
final int top = (textureHeight-height) / 2;
|
||||
|
||||
mOldBounds.set(icon.getBounds());
|
||||
if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
|
||||
int offset = Math.max((int)(BLUR_FACTOR * textureWidth), Math.min(left, top));
|
||||
int size = Math.max(width, height);
|
||||
icon.setBounds(offset, offset, size, size);
|
||||
} else {
|
||||
icon.setBounds(left, top, left+width, top+height);
|
||||
}
|
||||
mCanvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
mCanvas.scale(scale, scale, textureWidth / 2, textureHeight / 2);
|
||||
icon.draw(mCanvas);
|
||||
mCanvas.restore();
|
||||
icon.setBounds(mOldBounds);
|
||||
mCanvas.setBitmap(null);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public static BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context) {
|
||||
return createShortcutIcon(shortcutInfo, context, true /* badged */);
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo) {
|
||||
return createShortcutIcon(shortcutInfo, true /* badged */);
|
||||
}
|
||||
|
||||
public static BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context,
|
||||
boolean badged) {
|
||||
return createShortcutIcon(shortcutInfo, context, badged, null);
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo, boolean badged) {
|
||||
return createShortcutIcon(shortcutInfo, badged, null);
|
||||
}
|
||||
|
||||
public static BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context,
|
||||
public BitmapInfo createShortcutIcon(ShortcutInfoCompat shortcutInfo,
|
||||
boolean badged, @Nullable Provider<Bitmap> fallbackIconProvider) {
|
||||
LauncherAppState app = LauncherAppState.getInstance(context);
|
||||
Drawable unbadgedDrawable = DeepShortcutManager.getInstance(context)
|
||||
.getShortcutIconDrawable(shortcutInfo,
|
||||
app.getInvariantDeviceProfile().fillResIconDpi);
|
||||
IconCache cache = app.getIconCache();
|
||||
Drawable unbadgedDrawable = DeepShortcutManager.getInstance(mContext)
|
||||
.getShortcutIconDrawable(shortcutInfo, mFillResIconDpi);
|
||||
IconCache cache = LauncherAppState.getInstance(mContext).getIconCache();
|
||||
|
||||
Bitmap unbadgedBitmap = null;
|
||||
if (unbadgedDrawable != null) {
|
||||
unbadgedBitmap = LauncherIcons.createScaledBitmapWithoutShadow(
|
||||
unbadgedDrawable, context, 0);
|
||||
unbadgedBitmap = createScaledBitmapWithoutShadow(unbadgedDrawable, 0);
|
||||
} else {
|
||||
if (fallbackIconProvider != null) {
|
||||
unbadgedBitmap = fallbackIconProvider.get();
|
||||
@@ -338,20 +340,18 @@ public class LauncherIcons {
|
||||
|
||||
BitmapInfo result = new BitmapInfo();
|
||||
if (!badged) {
|
||||
result.color = Themes.getColorAccent(context);
|
||||
result.color = Themes.getColorAccent(mContext);
|
||||
result.icon = unbadgedBitmap;
|
||||
return result;
|
||||
}
|
||||
|
||||
int size = app.getInvariantDeviceProfile().iconBitmapSize;
|
||||
|
||||
final Bitmap unbadgedfinal = unbadgedBitmap;
|
||||
final ItemInfoWithIcon badge = getShortcutInfoBadge(shortcutInfo, cache);
|
||||
|
||||
result.color = badge.iconColor;
|
||||
result.icon = UiFactory.createFromRenderer(size, size, false, (c) -> {
|
||||
ShadowGenerator.getInstance(context).recreateIcon(unbadgedfinal, c);
|
||||
badgeWithDrawable(c, new FastBitmapDrawable(badge), context);
|
||||
result.icon = UiFactory.createFromRenderer(mIconBitmapSize, mIconBitmapSize, false, (c) -> {
|
||||
getShadowGenerator().recreateIcon(unbadgedfinal, c);
|
||||
badgeWithDrawable(c, new FastBitmapDrawable(badge));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -46,17 +46,13 @@ public class ShadowGenerator {
|
||||
|
||||
private static final int AMBIENT_SHADOW_ALPHA = 30;
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
// Singleton object guarded by {@link #LOCK}
|
||||
private static ShadowGenerator sShadowGenerator;
|
||||
|
||||
private final int mIconSize;
|
||||
|
||||
private final Paint mBlurPaint;
|
||||
private final Paint mDrawPaint;
|
||||
private final BlurMaskFilter mDefaultBlurMaskFilter;
|
||||
|
||||
private ShadowGenerator(Context context) {
|
||||
public ShadowGenerator(Context context) {
|
||||
mIconSize = LauncherAppState.getIDP(context).iconBitmapSize;
|
||||
mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||
mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||
@@ -86,18 +82,6 @@ public class ShadowGenerator {
|
||||
out.drawBitmap(icon, 0, 0, mDrawPaint);
|
||||
}
|
||||
|
||||
public static ShadowGenerator getInstance(Context context) {
|
||||
// TODO: This currently fails as the system default icon also needs a shadow as it
|
||||
// uses adaptive icon.
|
||||
// Preconditions.assertNonUiThread();
|
||||
synchronized (LOCK) {
|
||||
if (sShadowGenerator == null) {
|
||||
sShadowGenerator = new ShadowGenerator(context);
|
||||
}
|
||||
}
|
||||
return sShadowGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum amount by which an icon with {@param bounds} should be scaled
|
||||
* so that the shadows do not get clipped.
|
||||
|
||||
@@ -173,7 +173,9 @@ public class LoaderCursor extends CursorWrapper {
|
||||
info.iconResource = new ShortcutIconResource();
|
||||
info.iconResource.packageName = packageName;
|
||||
info.iconResource.resourceName = resourceName;
|
||||
BitmapInfo iconInfo = LauncherIcons.createIconBitmap(info.iconResource, mContext);
|
||||
LauncherIcons li = LauncherIcons.obtain(mContext);
|
||||
BitmapInfo iconInfo = li.createIconBitmap(info.iconResource);
|
||||
li.recycle();
|
||||
if (iconInfo != null) {
|
||||
iconInfo.applyTo(info);
|
||||
return true;
|
||||
@@ -183,9 +185,8 @@ public class LoaderCursor extends CursorWrapper {
|
||||
|
||||
// Failed to load from resource, try loading from DB.
|
||||
byte[] data = getBlob(iconIndex);
|
||||
try {
|
||||
LauncherIcons.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length),
|
||||
mContext).applyTo(info);
|
||||
try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
|
||||
li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)).applyTo(info);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to load icon for info " + info, e);
|
||||
|
||||
@@ -215,9 +215,10 @@ public class LoaderTask implements Runnable {
|
||||
|
||||
public void loadUiResources() {
|
||||
if (Utilities.ATLEAST_OREO) {
|
||||
ClickShadowView.setAdaptiveIconScaleFactor(
|
||||
IconNormalizer.getInstance(mApp.getContext()).getScale(
|
||||
new AdaptiveIconDrawable(null, null), null, null, null));
|
||||
LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
|
||||
ClickShadowView.setAdaptiveIconScaleFactor(li.getNormalizer()
|
||||
.getScale(new AdaptiveIconDrawable(null, null), null, null, null));
|
||||
li.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,8 +477,10 @@ public class LoaderTask implements Runnable {
|
||||
? finalInfo.iconBitmap : null;
|
||||
}
|
||||
};
|
||||
LauncherIcons.createShortcutIcon(pinnedShortcut, context,
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
li.createShortcutIcon(pinnedShortcut,
|
||||
true /* badged */, fallbackIconProvider).applyTo(info);
|
||||
li.recycle();
|
||||
if (pmHelper.isAppSuspended(
|
||||
pinnedShortcut.getPackage(), info.user)) {
|
||||
info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED;
|
||||
|
||||
@@ -192,8 +192,9 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
||||
// Update shortcuts which use iconResource.
|
||||
if ((si.iconResource != null)
|
||||
&& packageSet.contains(si.iconResource.packageName)) {
|
||||
BitmapInfo iconInfo =
|
||||
LauncherIcons.createIconBitmap(si.iconResource, context);
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
BitmapInfo iconInfo = li.createIconBitmap(si.iconResource);
|
||||
li.recycle();
|
||||
if (iconInfo != null) {
|
||||
iconInfo.applyTo(si);
|
||||
infoUpdated = true;
|
||||
|
||||
@@ -95,8 +95,10 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask {
|
||||
shortcutInfo.updateFromDeepShortcutInfo(fullDetails, context);
|
||||
// If the shortcut is pinned but no longer has an icon in the system,
|
||||
// keep the current icon instead of reverting to the default icon.
|
||||
LauncherIcons.createShortcutIcon(fullDetails, context, true,
|
||||
Provider.of(shortcutInfo.iconBitmap)).applyTo(shortcutInfo);
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
li.createShortcutIcon(fullDetails, true, Provider.of(shortcutInfo.iconBitmap))
|
||||
.applyTo(shortcutInfo);
|
||||
li.recycle();
|
||||
updatedShortcutInfos.add(shortcutInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +94,9 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask {
|
||||
si.updateFromDeepShortcutInfo(shortcut, context);
|
||||
// If the shortcut is pinned but no longer has an icon in the system,
|
||||
// keep the current icon instead of reverting to the default icon.
|
||||
LauncherIcons.createShortcutIcon(shortcut, context, true,
|
||||
Provider.of(si.iconBitmap)).applyTo(si);
|
||||
LauncherIcons li = LauncherIcons.obtain(context);
|
||||
li.createShortcutIcon(shortcut, true, Provider.of(si.iconBitmap)).applyTo(si);
|
||||
li.recycle();
|
||||
} else {
|
||||
si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
|
||||
}
|
||||
|
||||
@@ -148,8 +148,9 @@ public class PopupPopulator {
|
||||
final ShortcutInfoCompat shortcut = shortcuts.get(i);
|
||||
final ShortcutInfo si = new ShortcutInfo(shortcut, launcher);
|
||||
// Use unbadged icon for the menu.
|
||||
LauncherIcons.createShortcutIcon(shortcut, launcher, false /* badged */)
|
||||
.applyTo(si);
|
||||
LauncherIcons li = LauncherIcons.obtain(launcher);
|
||||
li.createShortcutIcon(shortcut, false /* badged */).applyTo(si);
|
||||
li.recycle();
|
||||
si.rank = i;
|
||||
|
||||
final DeepShortcutView view = shortcutViews.get(i);
|
||||
|
||||
@@ -113,7 +113,9 @@ public class PendingItemDragHelper extends DragPreviewProvider {
|
||||
} else {
|
||||
PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo;
|
||||
Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache());
|
||||
preview = LauncherIcons.createScaledBitmapWithoutShadow(icon, launcher, 0);
|
||||
LauncherIcons li = LauncherIcons.obtain(launcher);
|
||||
preview = li.createScaledBitmapWithoutShadow(icon, 0);
|
||||
li.recycle();
|
||||
scale = ((float) launcher.getDeviceProfile().iconSizePx) / preview.getWidth();
|
||||
|
||||
dragOffset = new Point(previewPadding / 2, previewPadding / 2);
|
||||
|
||||
Reference in New Issue
Block a user