Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7aa626b5 authored by Fan Zhang's avatar Fan Zhang
Browse files

Support customizing icon color for externally items.

When a setting is injected to homepage, we now allow the setting
provider customize the background color for its icon.

If no custom bg color is provided, we fallback to existing behavior.

This behavior is only needed in homepage, because we don't have any
tinting logic in other pages so external setting providers can just
provide arbitrary icon.

Bug: 77188317
Test: robotests
Change-Id: I7d4b512fafc28537de46192026ce4bbe51b498c4
parent 3441c3b0
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.settings.dashboard;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.service.settings.suggestions.Suggestion;
@@ -47,6 +48,7 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
import com.android.settingslib.suggestions.SuggestionControllerMixin;
import com.android.settingslib.utils.IconCache;

@@ -316,6 +318,20 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
        if (!TextUtils.equals(tile.icon.getResPackage(), mContext.getPackageName())
                && !(icon instanceof RoundedHomepageIcon)) {
            icon = new RoundedHomepageIcon(mContext, icon);
            try {
                if (tile.metaData != null) {
                    final int colorRes = tile.metaData.getInt(
                            TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT, 0 /* default */);
                    if (colorRes != 0) {
                        final int bgColor = mContext.getPackageManager()
                                .getResourcesForApplication(tile.icon.getResPackage())
                                .getColor(colorRes, null /* theme */);
                        ((RoundedHomepageIcon) icon).setBackgroundColor(bgColor);
                    }
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(TAG, "Failed to set background color for " + tile.intent.getPackage());
            }
            mCache.updateIcon(tile.icon, icon);
        }
        holder.icon.setImageDrawable(icon);
+12 −0
Original line number Diff line number Diff line
@@ -16,14 +16,21 @@

package com.android.settings.dashboard;

import static android.support.annotation.VisibleForTesting.NONE;

import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.annotation.VisibleForTesting;

import com.android.settings.R;

public class RoundedHomepageIcon extends LayerDrawable {

    @VisibleForTesting(otherwise = NONE)
    int mBackgroundColor = -1;

    public RoundedHomepageIcon(Context context, Drawable foreground) {
        super(new Drawable[] {
                context.getDrawable(R.drawable.ic_homepage_generic_background),
@@ -33,4 +40,9 @@ public class RoundedHomepageIcon extends LayerDrawable {
                .getDimensionPixelSize(R.dimen.dashboard_tile_foreground_image_inset);
        setLayerInset(1 /* index */, insetPx, insetPx, insetPx, insetPx);
    }

    public void setBackgroundColor(int color) {
        mBackgroundColor = color;
        getDrawable(0).setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
    }
}
+32 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.dashboard;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -30,6 +31,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.service.settings.suggestions.Suggestion;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
@@ -46,6 +48,7 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
import com.android.settingslib.utils.IconCache;

import org.junit.Before;
@@ -193,24 +196,48 @@ public class DashboardAdapterTest {

    @Test
    public void onBindTile_externalTile_shouldUpdateIcon() {
        final Context context = RuntimeEnvironment.application;
        final Context context = spy(RuntimeEnvironment.application);
        final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
        final DashboardAdapter.DashboardItemHolder holder =
                new DashboardAdapter.DashboardItemHolder(view);
        final Tile tile = new Tile();
        tile.icon = mock(Icon.class);
        tile.icon = Icon.createWithResource(context, R.drawable.ic_settings);
        when(tile.icon.getResPackage()).thenReturn("another.package");

        final IconCache iconCache = mock(IconCache.class);
        when(iconCache.getIcon(tile.icon)).thenReturn(context.getDrawable(R.drawable.ic_settings));
        final IconCache iconCache = new IconCache(context);

        mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
        ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);

        doReturn("another.package").when(context).getPackageName();
        mDashboardAdapter.onBindTile(holder, tile);

        assertThat(iconCache.getIcon(tile.icon)).isInstanceOf(RoundedHomepageIcon.class);
    }

    @Test
    public void onBindTile_externalTileWithBackgroundColorHint_shouldUpdateIcon() {
        final Context context = spy(RuntimeEnvironment.application);
        final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null);
        final DashboardAdapter.DashboardItemHolder holder =
                new DashboardAdapter.DashboardItemHolder(view);
        final Tile tile = new Tile();
        tile.metaData = new Bundle();
        tile.metaData.putInt(TileUtils.META_DATA_PREFERENCE_ICON_BACKGROUND_HINT,
                R.color.memory_critical);
        tile.icon = Icon.createWithResource(context, R.drawable.ic_settings);
        final IconCache iconCache = new IconCache(context);
        mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */,
                null /* conditions */, null /* suggestionControllerMixin */, null /* lifecycle */);
        ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache);

        doReturn("another.package").when(context).getPackageName();
        mDashboardAdapter.onBindTile(holder, tile);

        verify(iconCache).updateIcon(eq(tile.icon), any(RoundedHomepageIcon.class));
        final RoundedHomepageIcon homepageIcon = (RoundedHomepageIcon) iconCache.getIcon(tile.icon);
        assertThat(homepageIcon.mBackgroundColor)
                .isEqualTo(RuntimeEnvironment.application.getColor(R.color.memory_critical));
    }

    @Test
+20 −2
Original line number Diff line number Diff line
@@ -17,10 +17,16 @@
package com.android.settings.dashboard;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.ShapeDrawable;

import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -49,4 +55,16 @@ public class RoundedHomepageIconTest {
        assertThat(icon.getDrawable(0))
                .isEqualTo(mContext.getDrawable(R.drawable.ic_homepage_generic_background));
    }

    @Test
    public void setBackgroundColor_shouldUpdateColorFilter() {
        final RoundedHomepageIcon icon =
                spy(new RoundedHomepageIcon(mContext, new ColorDrawable(Color.BLACK)));
        final ShapeDrawable background = mock(ShapeDrawable.class);
        when(icon.getDrawable(0)).thenReturn(background);

        icon.setBackgroundColor(Color.BLUE);

        verify(background).setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_ATOP);
    }
}