Add activityInfo and getIcon() method in Tile class.
Moved loading icon logic from TileUtils into Tile#getIcon().
TileUtils only load things once and cache forever but getIcon()
loads a fresh icon every time to avoid any caching issue.
Bug: 77600770
Test: robotests
Change-Id: I706225e382ebd5b72e91edef43bfc7427fa64590
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index 0c802af..47624ff 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -17,17 +17,19 @@
package com.android.settingslib.drawer;
import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.widget.RemoteViews;
import java.util.ArrayList;
@@ -36,25 +38,24 @@
*/
public class Tile implements Parcelable {
+ private static final String TAG = "Tile";
+ private ActivityInfo mActivityInfo;
+
/**
* Title of the tile that is shown to the user.
+ *
* @attr ref android.R.styleable#PreferenceHeader_title
*/
public CharSequence title;
/**
* Optional summary describing what this tile controls.
+ *
* @attr ref android.R.styleable#PreferenceHeader_summary
*/
public CharSequence summary;
/**
- * Optional icon to show for this tile.
- * @attr ref android.R.styleable#PreferenceHeader_icon
- */
- 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.
*/
@@ -95,8 +96,8 @@
*/
public String key;
- public Tile() {
- // Empty
+ public Tile(ActivityInfo activityInfo) {
+ mActivityInfo = activityInfo;
}
@Override
@@ -106,14 +107,9 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mActivityInfo, flags);
TextUtils.writeToParcel(title, dest, flags);
TextUtils.writeToParcel(summary, dest, flags);
- if (icon != null) {
- dest.writeByte((byte) 1);
- icon.writeToParcel(dest, flags);
- } else {
- dest.writeByte((byte) 0);
- }
if (intent != null) {
dest.writeByte((byte) 1);
intent.writeToParcel(dest, flags);
@@ -133,13 +129,37 @@
dest.writeBoolean(isIconTintable);
}
+ /**
+ * Optional icon to show for this tile.
+ *
+ * @attr ref android.R.styleable#PreferenceHeader_icon
+ */
+ public Icon getIcon() {
+ if (mActivityInfo == null || metaData == null) {
+ return null;
+ }
+ int iconResId = metaData.getInt(META_DATA_PREFERENCE_ICON);
+ // Set the icon
+ if (iconResId == 0) {
+ // Only fallback to activityinfo.icon if metadata does not contain ICON_URI.
+ // ICON_URI should be loaded in app UI when need the icon object. Handling IPC at this
+ // level is too complex because we don't have a strong threading contract for this class
+ if (!metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
+ iconResId = mActivityInfo.icon;
+ }
+ }
+ if (iconResId != 0) {
+ return Icon.createWithResource(mActivityInfo.packageName, iconResId);
+ } else {
+ return null;
+ }
+ }
+
public void readFromParcel(Parcel in) {
+ mActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
if (in.readByte() != 0) {
- icon = Icon.CREATOR.createFromParcel(in);
- }
- if (in.readByte() != 0) {
intent = Intent.CREATOR.createFromParcel(in);
}
final int N = in.readInt();
@@ -162,6 +182,7 @@
public Tile createFromParcel(Parcel source) {
return new Tile(source);
}
+
public Tile[] newArray(int size) {
return new Tile[size];
}
@@ -169,7 +190,7 @@
public boolean isPrimaryProfileOnly() {
String profile = metaData != null ?
- metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
+ metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
profile = (profile != null ? profile : PROFILE_ALL);
return TextUtils.equals(profile, PROFILE_PRIMARY);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 06f1456..11976d7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
@@ -303,7 +302,7 @@
Pair<String, String> key = new Pair<>(activityInfo.packageName, activityInfo.name);
Tile tile = addedCache.get(key);
if (tile == null) {
- tile = new Tile();
+ tile = new Tile(activityInfo);
tile.intent = new Intent().setClassName(
activityInfo.packageName, activityInfo.name);
tile.category = categoryKey;
@@ -329,7 +328,6 @@
boolean forceTintExternalIcon) {
if (applicationInfo.isSystemApp()) {
boolean forceTintIcon = false;
- int icon = 0;
CharSequence title = null;
String summary = null;
String keyHint = null;
@@ -347,9 +345,6 @@
}
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);
@@ -390,18 +385,6 @@
title = activityInfo.loadLabel(pm).toString();
}
- // Set the icon
- if (icon == 0) {
- // Only fallback to activityinfo.icon if metadata does not contain ICON_URI.
- // ICON_URI should be loaded in app UI when need the icon object.
- if (!tile.metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
- icon = activityInfo.icon;
- }
- }
- if (icon != 0) {
- tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
- }
-
// Set title and summary for the preference
tile.title = title;
tile.summary = summary;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
index ac2d759..63f462c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
@@ -16,8 +16,16 @@
package com.android.settingslib.drawer;
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
@@ -30,12 +38,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ProfileSelectDialogTest {
@@ -58,7 +60,7 @@
@Test
public void testUpdateUserHandlesIfNeeded_Normal() {
- final Tile tile = new Tile();
+ final Tile tile = new Tile(new ActivityInfo());
tile.intent = new Intent();
tile.userHandle.add(NORMAL_USER);
@@ -71,7 +73,7 @@
@Test
public void testUpdateUserHandlesIfNeeded_Remove() {
- final Tile tile = new Tile();
+ final Tile tile = new Tile(new ActivityInfo());
tile.intent = new Intent();
tile.userHandle.add(REMOVED_USER);
tile.userHandle.add(NORMAL_USER);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index 7b9f92a..f03b334 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -1,27 +1,37 @@
package com.android.settingslib.drawer;
import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
+import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
import static com.google.common.truth.Truth.assertThat;
+import android.content.pm.ActivityInfo;
import android.os.Bundle;
+import com.android.settingslib.R;
import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
@RunWith(SettingsLibRobolectricTestRunner.class)
public class TileTest {
+ private ActivityInfo mActivityInfo;
private Tile mTile;
@Before
public void setUp() {
- mTile = new Tile();
+ mActivityInfo = new ActivityInfo();
+ mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
+ mActivityInfo.icon = R.drawable.ic_plus;
+ mTile = new Tile(mActivityInfo);
mTile.metaData = new Bundle();
}
@@ -47,4 +57,34 @@
mTile.metaData = null;
assertThat(mTile.isPrimaryProfileOnly()).isFalse();
}
+
+ @Test
+ public void getIcon_noActivityOrMetadata_returnNull() {
+ final Tile tile1 = new Tile((ActivityInfo) null);
+ assertThat(tile1.getIcon()).isNull();
+
+ final Tile tile2 = new Tile(new ActivityInfo());
+ assertThat(tile2.getIcon()).isNull();
+ }
+
+ @Test
+ public void getIcon_providedByUri_returnNull() {
+ mTile.metaData.putString(META_DATA_PREFERENCE_ICON_URI, "content://foobar/icon");
+
+ assertThat(mTile.getIcon()).isNull();
+ }
+
+ @Test
+ public void getIcon_hasIconMetadata_returnIcon() {
+ mTile.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_info);
+
+ assertThat(mTile.getIcon().getResId()).isEqualTo(R.drawable.ic_info);
+ }
+
+ @Test
+ public void getIcon_noIconMetadata_returnActivityIcon() {
+ mTile.metaData.putInt(META_DATA_PREFERENCE_ICON, 0);
+
+ assertThat(mTile.getIcon().getResId()).isEqualTo(mActivityInfo.icon);
+ }
}
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 a1c48f0..e6c6335 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
@@ -314,7 +314,7 @@
false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
- assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
+ assertThat(outTiles.get(0).getIcon().getResId()).isEqualTo(314159);
assertThat(outTiles.get(0).summary).isEqualTo("static-summary");
// Case 2: Empty bundle.
@@ -332,7 +332,7 @@
false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
- assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
+ assertThat(outTiles.get(0).getIcon().getResId()).isEqualTo(314159);
assertThat(outTiles.get(0).summary).isEqualTo("static-summary");
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
index 1acb04e..fa64afe 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
@@ -237,7 +237,7 @@
assertThat(InputMethodAndSubtypeUtilCompat.isValidSystemNonAuxAsciiCapableIme(
createDummyIme(false, false, createDummySubtype("keyboard", false, true))))
.isFalse();
- }
+ }
private static InputMethodInfo createDummyIme(boolean isSystem, boolean isAuxIme,
InputMethodSubtype... subtypes) {
@@ -254,7 +254,7 @@
si.exported = true;
si.nonLocalizedLabel = "Dummy IME";
ri.serviceInfo = si;
- return new InputMethodInfo(ri, isAuxIme, "", Arrays.asList(subtypes), 1, false);
+ return new InputMethodInfo(ri, isAuxIme, "", Arrays.asList(subtypes), 1, false);
}
private static InputMethodSubtype createDummySubtype(
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
index 57c69f4..1e066b1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
@@ -58,7 +58,7 @@
}
@Test
- public void testPostOnMainThread_shouldRunOnMainTread() throws Exception {
+ public void testPostOnMainThread_shouldRunOnMainTread() {
TestRunnable cr = new TestRunnable();
ShadowLooper.pauseMainLooper();
ThreadUtils.postOnMainThread(cr);