Add default icons for all mode types
Also a couple of icon-related fixes: * Use the proper context, since we need theming (this also means it cannot be stored in IconLoader, which is a singleton, and must be supplied). * Force apply the standard size and tint, since app-provided icons may be arbitrary. * Fix the schedule-time icon (the viewport size was incorrect). Bug: 308819461 Fixes: 333528437 Flag: android.app.modes_ui Test: atest com.android.settings.notification.modes Change-Id: Iae447c8c4a0218a8bc989c01d1d56d0c06abd8e7
This commit is contained in:
@@ -56,47 +56,42 @@ class IconLoader {
|
||||
@Nullable // Until first usage
|
||||
private static IconLoader sInstance;
|
||||
|
||||
private final Context mContext;
|
||||
private final LruCache<String, Drawable> mCache;
|
||||
private final ListeningExecutorService mBackgroundExecutor;
|
||||
|
||||
static IconLoader getInstance(Context context) {
|
||||
static IconLoader getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new IconLoader(context);
|
||||
sInstance = new IconLoader();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private IconLoader(Context context) {
|
||||
this(context, Executors.newFixedThreadPool(4));
|
||||
private IconLoader() {
|
||||
this(Executors.newFixedThreadPool(4));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
IconLoader(Context context, ExecutorService backgroundExecutor) {
|
||||
mContext = context.getApplicationContext();
|
||||
IconLoader(ExecutorService backgroundExecutor) {
|
||||
mCache = new LruCache<>(50);
|
||||
mBackgroundExecutor =
|
||||
MoreExecutors.listeningDecorator(backgroundExecutor);
|
||||
}
|
||||
|
||||
Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
ListenableFuture<Drawable> getIcon(@NonNull AutomaticZenRule rule) {
|
||||
ListenableFuture<Drawable> getIcon(Context context, @NonNull AutomaticZenRule rule) {
|
||||
if (rule.getIconResId() == 0) {
|
||||
return Futures.immediateFuture(getFallbackIcon(rule.getType()));
|
||||
return Futures.immediateFuture(getFallbackIcon(context, rule.getType()));
|
||||
}
|
||||
|
||||
return FluentFuture.from(loadIcon(rule.getPackageName(), rule.getIconResId()))
|
||||
return FluentFuture.from(loadIcon(context, rule.getPackageName(), rule.getIconResId()))
|
||||
.transform(icon ->
|
||||
icon != null ? icon : getFallbackIcon(rule.getType()),
|
||||
icon != null ? icon : getFallbackIcon(context, rule.getType()),
|
||||
MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ListenableFuture</* @Nullable */ Drawable> loadIcon(String pkg, int iconResId) {
|
||||
private ListenableFuture</* @Nullable */ Drawable> loadIcon(Context context, String pkg,
|
||||
int iconResId) {
|
||||
String cacheKey = pkg + ":" + iconResId;
|
||||
synchronized (mCache) {
|
||||
Drawable cachedValue = mCache.get(cacheKey);
|
||||
@@ -107,9 +102,9 @@ class IconLoader {
|
||||
|
||||
return FluentFuture.from(mBackgroundExecutor.submit(() -> {
|
||||
if (TextUtils.isEmpty(pkg) || SystemZenRules.PACKAGE_ANDROID.equals(pkg)) {
|
||||
return mContext.getDrawable(iconResId);
|
||||
return context.getDrawable(iconResId);
|
||||
} else {
|
||||
Context appContext = mContext.createPackageContext(pkg, 0);
|
||||
Context appContext = context.createPackageContext(pkg, 0);
|
||||
Drawable appDrawable = AppCompatResources.getDrawable(appContext, iconResId);
|
||||
return getMonochromeIconIfPresent(appDrawable);
|
||||
}
|
||||
@@ -126,21 +121,21 @@ class IconLoader {
|
||||
}, MoreExecutors.directExecutor());
|
||||
}
|
||||
|
||||
private Drawable getFallbackIcon(int ruleType) {
|
||||
private static Drawable getFallbackIcon(Context context, int ruleType) {
|
||||
int iconResIdFromType = switch (ruleType) {
|
||||
// TODO: b/333528437 - continue replacing with proper default icons
|
||||
case AutomaticZenRule.TYPE_UNKNOWN -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_OTHER -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_SCHEDULE_TIME -> R.drawable.ic_modes_time;
|
||||
case AutomaticZenRule.TYPE_SCHEDULE_CALENDAR -> R.drawable.ic_modes_event;
|
||||
case AutomaticZenRule.TYPE_BEDTIME -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_DRIVING -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_IMMERSIVE -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_THEATER -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_MANAGED -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
default -> R.drawable.ic_do_not_disturb_on_24dp;
|
||||
case AutomaticZenRule.TYPE_UNKNOWN -> R.drawable.ic_zen_mode_type_unknown;
|
||||
case AutomaticZenRule.TYPE_OTHER -> R.drawable.ic_zen_mode_type_other;
|
||||
case AutomaticZenRule.TYPE_SCHEDULE_TIME -> R.drawable.ic_zen_mode_type_schedule_time;
|
||||
case AutomaticZenRule.TYPE_SCHEDULE_CALENDAR ->
|
||||
R.drawable.ic_zen_mode_type_schedule_calendar;
|
||||
case AutomaticZenRule.TYPE_BEDTIME -> R.drawable.ic_zen_mode_type_bedtime;
|
||||
case AutomaticZenRule.TYPE_DRIVING -> R.drawable.ic_zen_mode_type_driving;
|
||||
case AutomaticZenRule.TYPE_IMMERSIVE -> R.drawable.ic_zen_mode_type_immersive;
|
||||
case AutomaticZenRule.TYPE_THEATER -> R.drawable.ic_zen_mode_type_theater;
|
||||
case AutomaticZenRule.TYPE_MANAGED -> R.drawable.ic_zen_mode_type_managed;
|
||||
default -> R.drawable.ic_zen_mode_type_unknown;
|
||||
};
|
||||
return requireNonNull(mContext.getDrawable(iconResIdFromType));
|
||||
return requireNonNull(context.getDrawable(iconResIdFromType));
|
||||
}
|
||||
|
||||
private static Drawable getMonochromeIconIfPresent(Drawable icon) {
|
||||
|
||||
@@ -118,14 +118,14 @@ class ZenMode {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ListenableFuture<Drawable> getIcon(@NonNull IconLoader iconLoader) {
|
||||
Context context = iconLoader.getContext();
|
||||
public ListenableFuture<Drawable> getIcon(@NonNull Context context,
|
||||
@NonNull IconLoader iconLoader) {
|
||||
if (mIsManualDnd) {
|
||||
return Futures.immediateFuture(requireNonNull(
|
||||
context.getDrawable(R.drawable.ic_do_not_disturb_on_24dp)));
|
||||
}
|
||||
|
||||
return iconLoader.getIcon(mRule);
|
||||
return iconLoader.getIcon(context, mRule);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -62,7 +62,7 @@ class ZenModeHeaderController extends AbstractZenModePreferenceController {
|
||||
}
|
||||
|
||||
FutureUtil.whenDone(
|
||||
zenMode.getIcon(IconLoader.getInstance(mContext)),
|
||||
zenMode.getIcon(mContext, IconLoader.getInstance()),
|
||||
icon -> mHeaderController.setIcon(icon)
|
||||
.setLabel(zenMode.getRule().getName())
|
||||
.done(false /* rebindActions */),
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.os.Bundle;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.notification.zen.ZenModeSettings;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.Utils;
|
||||
|
||||
/**
|
||||
* Preference representing a single mode item on the modes aggregator page. Clicking on this
|
||||
@@ -64,10 +65,15 @@ class ZenModeListPreference extends RestrictedPreference {
|
||||
mZenMode = zenMode;
|
||||
setTitle(mZenMode.getRule().getName());
|
||||
setSummary(mZenMode.getRule().getTriggerDescription());
|
||||
setIconSize(ICON_SIZE_SMALL);
|
||||
|
||||
FutureUtil.whenDone(
|
||||
mZenMode.getIcon(IconLoader.getInstance(mContext)),
|
||||
icon -> setIcon(icon),
|
||||
mZenMode.getIcon(mContext, IconLoader.getInstance()),
|
||||
icon -> {
|
||||
icon.setTintList(
|
||||
Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
|
||||
setIcon(icon);
|
||||
},
|
||||
mContext.getMainExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user