Adding icon theming API support in Launcher
Bug: 200082620 Test: manual Change-Id: If986b9cfc3db79d627d2a6f1304e1b6f58491470
This commit is contained in:
@@ -36,6 +36,7 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.launcher3.icons.LauncherIconProvider;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.notification.NotificationListener;
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
@@ -61,7 +62,7 @@ public class LauncherAppState implements SafeCloseable {
|
||||
|
||||
private final Context mContext;
|
||||
private final LauncherModel mModel;
|
||||
private final IconProvider mIconProvider;
|
||||
private final LauncherIconProvider mIconProvider;
|
||||
private final IconCache mIconCache;
|
||||
private final InvariantDeviceProfile mInvariantDeviceProfile;
|
||||
private final RunnableList mOnTerminateCallback = new RunnableList();
|
||||
@@ -138,7 +139,7 @@ public class LauncherAppState implements SafeCloseable {
|
||||
mContext = context;
|
||||
|
||||
mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context);
|
||||
mIconProvider = new IconProvider(context, Themes.isThemedIconEnabled(context));
|
||||
mIconProvider = new LauncherIconProvider(context);
|
||||
mIconCache = new IconCache(mContext, mInvariantDeviceProfile,
|
||||
iconCacheFileName, mIconProvider);
|
||||
mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
|
||||
|
||||
@@ -76,9 +76,8 @@ import androidx.core.os.BuildCompat;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
import com.android.launcher3.graphics.GridCustomizationsProvider;
|
||||
import com.android.launcher3.graphics.TintedDrawableSpan;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.ShortcutCachingLogic;
|
||||
import com.android.launcher3.icons.ThemedIconDrawable;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.SearchActionItemInfo;
|
||||
@@ -87,6 +86,7 @@ import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
@@ -123,8 +123,9 @@ public final class Utilities {
|
||||
|
||||
public static final boolean ATLEAST_R = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
|
||||
|
||||
public static final boolean ATLEAST_S = BuildCompat.isAtLeastS()
|
||||
|| Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
|
||||
public static final boolean ATLEAST_S = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
|
||||
|
||||
public static final boolean ATLEAST_T = BuildCompat.isAtLeastT();
|
||||
|
||||
/**
|
||||
* Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
|
||||
@@ -672,11 +673,19 @@ public final class Utilities {
|
||||
* @param outObj this is set to the internal data associated with {@param info},
|
||||
* eg {@link LauncherActivityInfo} or {@link ShortcutInfo}.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.TIRAMISU)
|
||||
public static Drawable getFullDrawable(Context context, ItemInfo info, int width, int height,
|
||||
Object[] outObj) {
|
||||
Drawable icon = loadFullDrawableWithoutTheme(context, info, width, height, outObj);
|
||||
if (icon instanceof BitmapInfo.Extender) {
|
||||
icon = ((BitmapInfo.Extender) icon).getThemedDrawable(context);
|
||||
if (ATLEAST_T && icon instanceof AdaptiveIconDrawable) {
|
||||
AdaptiveIconDrawable aid = (AdaptiveIconDrawable) icon.mutate();
|
||||
Drawable mono = aid.getMonochrome();
|
||||
if (mono != null && Themes.isThemedIconEnabled(context)) {
|
||||
int[] colors = ThemedIconDrawable.getColors(context);
|
||||
mono = mono.mutate();
|
||||
mono.setTint(colors[1]);
|
||||
return new AdaptiveIconDrawable(new ColorDrawable(colors[0]), mono);
|
||||
}
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
@@ -719,8 +728,7 @@ public final class Utilities {
|
||||
return icon;
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION
|
||||
&& info instanceof SearchActionItemInfo) {
|
||||
return new AdaptiveIconDrawable(
|
||||
new FastBitmapDrawable(((SearchActionItemInfo) info).bitmap), null);
|
||||
return ((SearchActionItemInfo) info).bitmap.newIcon(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -133,23 +133,25 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
mObjectMap.put(InvariantDeviceProfile.INSTANCE, idp);
|
||||
mObjectMap.put(LauncherAppState.INSTANCE,
|
||||
new LauncherAppState(this, null /* iconCacheFileName */));
|
||||
|
||||
}
|
||||
|
||||
public LauncherIcons newLauncherIcons(Context context, boolean shapeDetection) {
|
||||
/**
|
||||
* Creates a new LauncherIcons for the preview, skipping the global pool
|
||||
*/
|
||||
public LauncherIcons newLauncherIcons(Context context) {
|
||||
LauncherIconsForPreview launcherIconsForPreview = mIconPool.poll();
|
||||
if (launcherIconsForPreview != null) {
|
||||
return launcherIconsForPreview;
|
||||
}
|
||||
return new LauncherIconsForPreview(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize,
|
||||
-1 /* poolId */, shapeDetection);
|
||||
-1 /* poolId */);
|
||||
}
|
||||
|
||||
private final class LauncherIconsForPreview extends LauncherIcons {
|
||||
|
||||
private LauncherIconsForPreview(Context context, int fillResIconDpi, int iconBitmapSize,
|
||||
int poolId, boolean shapeDetection) {
|
||||
super(context, fillResIconDpi, iconBitmapSize, poolId, shapeDetection);
|
||||
int poolId) {
|
||||
super(context, fillResIconDpi, iconBitmapSize, poolId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Extension of {@link IconProvider} with support for overriding theme icons
|
||||
*/
|
||||
public class LauncherIconProvider extends IconProvider {
|
||||
|
||||
private static final String TAG_ICON = "icon";
|
||||
private static final String ATTR_PACKAGE = "package";
|
||||
private static final String ATTR_DRAWABLE = "drawable";
|
||||
|
||||
private static final String TAG = "LIconProvider";
|
||||
private static final Map<String, ThemeData> DISABLED_MAP = Collections.emptyMap();
|
||||
|
||||
private Map<String, ThemeData> mThemedIconMap;
|
||||
private boolean mSupportsIconTheme;
|
||||
|
||||
public LauncherIconProvider(Context context) {
|
||||
super(context);
|
||||
setIconThemeSupported(Themes.isThemedIconEnabled(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables icon theme support
|
||||
*/
|
||||
public void setIconThemeSupported(boolean isSupported) {
|
||||
mSupportsIconTheme = isSupported;
|
||||
mThemedIconMap = isSupported ? null : DISABLED_MAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThemeData getThemeDataForPackage(String packageName) {
|
||||
return getThemedIconMap().get(packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSystemIconState() {
|
||||
return super.getSystemIconState() + (mSupportsIconTheme ? ",with-theme" : ",no-theme");
|
||||
}
|
||||
|
||||
private Map<String, ThemeData> getThemedIconMap() {
|
||||
if (mThemedIconMap != null) {
|
||||
return mThemedIconMap;
|
||||
}
|
||||
ArrayMap<String, ThemeData> map = new ArrayMap<>();
|
||||
Resources res = mContext.getResources();
|
||||
try (XmlResourceParser parser = res.getXml(R.xml.grayscale_icon_map)) {
|
||||
final int depth = parser.getDepth();
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.START_TAG
|
||||
&& type != XmlPullParser.END_DOCUMENT);
|
||||
|
||||
while (((type = parser.next()) != XmlPullParser.END_TAG
|
||||
|| parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
if (TAG_ICON.equals(parser.getName())) {
|
||||
String pkg = parser.getAttributeValue(null, ATTR_PACKAGE);
|
||||
int iconId = parser.getAttributeResourceValue(null, ATTR_DRAWABLE, 0);
|
||||
if (iconId != 0 && !TextUtils.isEmpty(pkg)) {
|
||||
map.put(pkg, new ThemeData(res, iconId));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to parse icon map", e);
|
||||
}
|
||||
mThemedIconMap = map;
|
||||
return mThemedIconMap;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.content.Context;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||
import com.android.launcher3.util.Themes;
|
||||
|
||||
/**
|
||||
* Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class
|
||||
@@ -32,18 +33,13 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
|
||||
private static LauncherIcons sPool;
|
||||
private static int sPoolId = 0;
|
||||
|
||||
public static LauncherIcons obtain(Context context) {
|
||||
return obtain(context, IconShape.getShape().enableShapeDetection());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, boolean shapeDetection) {
|
||||
public static LauncherIcons obtain(Context context) {
|
||||
if (context instanceof LauncherPreviewRenderer.PreviewContext) {
|
||||
return ((LauncherPreviewRenderer.PreviewContext) context).newLauncherIcons(context,
|
||||
shapeDetection);
|
||||
return ((LauncherPreviewRenderer.PreviewContext) context).newLauncherIcons(context);
|
||||
}
|
||||
|
||||
int poolId;
|
||||
@@ -58,8 +54,7 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
|
||||
}
|
||||
|
||||
InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context);
|
||||
return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize, poolId,
|
||||
shapeDetection);
|
||||
return new LauncherIcons(context, idp.fillResIconDpi, idp.iconBitmapSize, poolId);
|
||||
}
|
||||
|
||||
public static void clearPool() {
|
||||
@@ -73,9 +68,9 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable {
|
||||
|
||||
private LauncherIcons next;
|
||||
|
||||
protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId,
|
||||
boolean shapeDetection) {
|
||||
super(context, fillResIconDpi, iconBitmapSize, shapeDetection);
|
||||
protected LauncherIcons(Context context, int fillResIconDpi, int iconBitmapSize, int poolId) {
|
||||
super(context, fillResIconDpi, iconBitmapSize, IconShape.getShape().enableShapeDetection());
|
||||
mMonoIconEnabled = Themes.isThemedIconEnabled(context);
|
||||
mPoolId = poolId;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user