diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index 5a1e603e7fa29..f1d43bfe4096a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -50,6 +50,12 @@ public class Tile implements Parcelable {
*/
public Icon icon;
+ /**
+ * Whether the icon can be tinted. This should be set to true for monochrome (single-color)
+ * icons that can be tinted to match the design.
+ */
+ public boolean isIconTintable;
+
/**
* Intent to launch when the preference is selected.
*/
@@ -126,6 +132,7 @@ public class Tile implements Parcelable {
dest.writeBundle(metaData);
dest.writeString(key);
dest.writeParcelable(remoteViews, flags);
+ dest.writeBoolean(isIconTintable);
}
public void readFromParcel(Parcel in) {
@@ -147,6 +154,7 @@ public class Tile implements Parcelable {
metaData = in.readBundle();
key = in.readString();
remoteViews = in.readParcelable(RemoteViews.class.getClassLoader());
+ isIconTintable = in.readBoolean();
}
Tile(Parcel in) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 04a3d1f815611..9620a9153f80f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -133,15 +133,25 @@ public class TileUtils {
/**
* Name of the meta-data item that should be set in the AndroidManifest.xml
- * to specify the title that should be displayed for the preference.
+ * to specify whether the icon is tintable. This should be a boolean value {@code true} or
+ * {@code false}, set using {@code android:value}
*/
- @Deprecated
- public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
+ public static final String META_DATA_PREFERENCE_ICON_TINTABLE =
+ "com.android.settings.icon_tintable";
/**
* Name of the meta-data item that should be set in the AndroidManifest.xml
* to specify the title that should be displayed for the preference.
+ *
+ *
Note: It is preferred to provide this value using {@code android:resource} with a string
+ * resource for localization.
*/
+ public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
+
+ /**
+ * @deprecated Use {@link #META_DATA_PREFERENCE_TITLE} with {@code android:resource}
+ */
+ @Deprecated
public static final String META_DATA_PREFERENCE_TITLE_RES_ID =
"com.android.settings.title.resid";
@@ -309,12 +319,13 @@ public class TileUtils {
intent.setPackage(settingPkg);
}
getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
- usePriority, true);
+ usePriority, true, true);
}
- public static void getTilesForIntent(Context context, UserHandle user, Intent intent,
+ public static void getTilesForIntent(
+ Context context, UserHandle user, Intent intent,
Map, Tile> addedCache, String defaultCategory, List outTiles,
- boolean usePriority, boolean checkCategory) {
+ boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon) {
PackageManager pm = context.getPackageManager();
List results = pm.queryIntentActivitiesAsUser(intent,
PackageManager.GET_META_DATA, user.getIdentifier());
@@ -350,7 +361,7 @@ public class TileUtils {
tile.priority = usePriority ? resolved.priority : 0;
tile.metaData = activityInfo.metaData;
updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
- pm, providerMap);
+ pm, providerMap, forceTintExternalIcon);
if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
addedCache.put(key, tile);
@@ -366,25 +377,40 @@ public class TileUtils {
private static boolean updateTileData(Context context, Tile tile,
ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm,
- Map providerMap) {
+ Map providerMap, boolean forceTintExternalIcon) {
if (applicationInfo.isSystemApp()) {
+ boolean forceTintIcon = false;
int icon = 0;
Pair iconFromUri = null;
CharSequence title = null;
String summary = null;
String keyHint = null;
+ boolean isIconTintable = false;
RemoteViews remoteViews = null;
// Get the activity's meta-data
try {
- Resources res = pm.getResourcesForApplication(
- applicationInfo.packageName);
+ Resources res = pm.getResourcesForApplication(applicationInfo.packageName);
Bundle metaData = activityInfo.metaData;
+ if (forceTintExternalIcon
+ && !context.getPackageName().equals(applicationInfo.packageName)) {
+ isIconTintable = true;
+ forceTintIcon = true;
+ }
+
if (res != null && metaData != null) {
if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
}
+ if (metaData.containsKey(META_DATA_PREFERENCE_ICON_TINTABLE)) {
+ if (forceTintIcon) {
+ Log.w(LOG_TAG, "Ignoring icon tintable for " + activityInfo);
+ } else {
+ isIconTintable =
+ metaData.getBoolean(META_DATA_PREFERENCE_ICON_TINTABLE);
+ }
+ }
int resId = 0;
if (metaData.containsKey(META_DATA_PREFERENCE_TITLE_RES_ID)) {
resId = metaData.getInt(META_DATA_PREFERENCE_TITLE_RES_ID);
@@ -392,8 +418,6 @@ public class TileUtils {
title = res.getString(resId);
}
}
- // Fallback to legacy title extraction if we couldn't get the title through
- // res id.
if ((resId == 0) && metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
@@ -457,6 +481,7 @@ public class TileUtils {
activityInfo.name);
// Suggest a key for this tile
tile.key = keyHint;
+ tile.isIconTintable = isIconTintable;
tile.remoteViews = remoteViews;
return true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
index a28bece100eb2..167ffe61e42ba 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
@@ -208,7 +208,7 @@ public class SuggestionParser {
intent.setPackage(category.pkg);
}
TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
- mAddCache, null, suggestions, true, false);
+ mAddCache, null, suggestions, true, false, false);
filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
if (!category.multiple && suggestions.size() > (countBefore + 1)) {
// If there are too many, remove them all and only re-add the one with the highest
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
index 22fd83c67667d..31abecda9a399 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
@@ -19,5 +19,5 @@ package com.android.settingslib;
public class TestConfig {
public static final int SDK_VERSION = 23;
public static final String MANIFEST_PATH =
- "frameworks/base/packages/SettingsLib/robotests/AndroidManifest.xml";
+ "frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml";
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 7cfb32d7bdb03..036441839b5bd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -16,6 +16,19 @@
package com.android.settingslib.drawer;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.RuntimeEnvironment.application;
+
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -50,8 +63,9 @@ import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
import org.robolectric.internal.ShadowExtractor;
import java.util.ArrayList;
@@ -59,20 +73,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
@@ -100,8 +100,11 @@ public class TileUtilsTest {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getResourcesForApplication(anyString())).thenReturn(mResources);
- mContentResolver = spy(RuntimeEnvironment.application.getContentResolver());
+ when(mPackageManager.getApplicationInfo(eq("abc"), anyInt()))
+ .thenReturn(application.getApplicationInfo());
+ mContentResolver = spy(application.getContentResolver());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getPackageName()).thenReturn("com.android.settings");
}
@Test
@@ -118,7 +121,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).category).isEqualTo(testCategory);
@@ -139,7 +142,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).key).isEqualTo(keyHint);
@@ -159,7 +162,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.isEmpty()).isTrue();
}
@@ -182,7 +185,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
SuggestionParser parser = new SuggestionParser(
@@ -255,7 +258,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).title).isEqualTo("my title");
@@ -279,10 +282,60 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).title).isEqualTo("my localized title");
+
+ // Icon should be tintable because the tile is not from settings package, and
+ // "forceTintExternalIcon" is set
+ assertThat(outTiles.get(0).isIconTintable).isTrue();
+ }
+
+ @Test
+ public void getTilesForIntent_shouldNotTintIconIfInSettingsPackage() {
+ Intent intent = new Intent();
+ Map, Tile> addedCache = new ArrayMap<>();
+ List outTiles = new ArrayList<>();
+ List info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123);
+ resolveInfo.activityInfo.packageName = "com.android.settings";
+ resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+ .thenReturn(info);
+
+ TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+ null /* defaultCategory */, outTiles, false /* usePriority */,
+ false /* checkCategory */, true /* forceTintExternalIcon */);
+
+ assertThat(outTiles.size()).isEqualTo(1);
+ assertThat(outTiles.get(0).isIconTintable).isFalse();
+ }
+
+ @Test
+ public void getTilesForIntent_shouldMarkIconTintableIfMetadataSet() {
+ Intent intent = new Intent();
+ Map, Tile> addedCache = new ArrayMap<>();
+ List outTiles = new ArrayList<>();
+ List info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123);
+ resolveInfo.activityInfo.metaData
+ .putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+ .thenReturn(info);
+
+ TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+ null /* defaultCategory */, outTiles, false /* usePriority */,
+ false /* checkCategory */, false /* forceTintExternalIcon */);
+
+ assertThat(outTiles.size()).isEqualTo(1);
+ assertThat(outTiles.get(0).isIconTintable).isTrue();
}
@Test
@@ -301,7 +354,7 @@ public class TileUtilsTest {
// Case 1: No provider associated with the uri specified.
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
@@ -319,7 +372,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
@@ -341,7 +394,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
}
@@ -362,7 +415,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
Tile tile = outTiles.get(0);
@@ -399,7 +452,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
Tile tile = outTiles.get(0);
@@ -437,7 +490,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
Tile tile = outTiles.get(0);
@@ -484,7 +537,9 @@ public class TileUtilsTest {
if (summaryUri != null) {
info.activityInfo.metaData.putString("com.android.settings.summary_uri", summaryUri);
}
- if (title != null) {
+ if (titleResId != 0) {
+ info.activityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title);
+ } else if (title != null) {
info.activityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title);
}
if (titleResId != 0) {