Merge "Update bluetooth preference to take user to new screen"
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index 85a766e..e3319e9 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -20,7 +20,7 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="apps_and_notification_screen"
     android:title="@string/app_and_notification_dashboard_title"
-    settings:initialExpandedChildrenCount="9">
+    settings:initialExpandedChildrenCount="7">
 
     <PreferenceCategory
         android:key="recent_apps_category"
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 937e6db..52ca127 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -17,6 +17,7 @@
 
 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.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 @@
         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);
diff --git a/src/com/android/settings/dashboard/RoundedHomepageIcon.java b/src/com/android/settings/dashboard/RoundedHomepageIcon.java
index 19749b9..d63b80a 100644
--- a/src/com/android/settings/dashboard/RoundedHomepageIcon.java
+++ b/src/com/android/settings/dashboard/RoundedHomepageIcon.java
@@ -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 @@
                 .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);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index 5256ac4..ad0b01f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -18,6 +18,7 @@
 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.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.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 @@
 
     @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);
 
-        verify(iconCache).updateIcon(eq(tile.icon), any(RoundedHomepageIcon.class));
+        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);
+
+        final RoundedHomepageIcon homepageIcon = (RoundedHomepageIcon) iconCache.getIcon(tile.icon);
+        assertThat(homepageIcon.mBackgroundColor)
+                .isEqualTo(RuntimeEnvironment.application.getColor(R.color.memory_critical));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/dashboard/RoundedHomepageIconTest.java b/tests/robotests/src/com/android/settings/dashboard/RoundedHomepageIconTest.java
index f270395..0c90660 100644
--- a/tests/robotests/src/com/android/settings/dashboard/RoundedHomepageIconTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/RoundedHomepageIconTest.java
@@ -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;
@@ -43,10 +49,22 @@
     @Test
     public void createIcon_shouldSetBackgroundAndInset() {
         final RoundedHomepageIcon icon =
-            new RoundedHomepageIcon(mContext, new ColorDrawable(Color.BLACK));
+                new RoundedHomepageIcon(mContext, new ColorDrawable(Color.BLACK));
 
         assertThat(icon.getNumberOfLayers()).isEqualTo(2);
         assertThat(icon.getDrawable(0))
-            .isEqualTo(mContext.getDrawable(R.drawable.ic_homepage_generic_background));
+                .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);
     }
 }