Cache the summary and icons for Security Settings injected tiles.
This helps the summary and icons load more smoothly when resuming from recents. Bug: 35994047 Test: make RunSettingsRoboTests Change-Id: I763f7dd19f64007959e1281f0ff04ecd19bbfbfc
This commit is contained in:
@@ -39,6 +39,7 @@ import com.android.settingslib.drawer.Tile;
|
|||||||
import com.android.settingslib.drawer.TileUtils;
|
import com.android.settingslib.drawer.TileUtils;
|
||||||
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/** Implementation for {@code SecurityFeatureProvider}. */
|
/** Implementation for {@code SecurityFeatureProvider}. */
|
||||||
@@ -51,6 +52,12 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String DEFAULT_SUMMARY = " ";
|
static final String DEFAULT_SUMMARY = " ";
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static Map<String, Pair<String, Integer>> sIconCache = new TreeMap<>();
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static Map<String, String> sSummaryCache = new TreeMap<>();
|
||||||
|
|
||||||
/** Update preferences with data from associated tiles. */
|
/** Update preferences with data from associated tiles. */
|
||||||
public void updatePreferences(final Context context, final PreferenceScreen preferenceScreen,
|
public void updatePreferences(final Context context, final PreferenceScreen preferenceScreen,
|
||||||
final DashboardCategory dashboardCategory) {
|
final DashboardCategory dashboardCategory) {
|
||||||
@@ -89,11 +96,33 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
|
|||||||
if (matchingPref == null) {
|
if (matchingPref == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Remove any icons that may be loaded before we inject the final icon.
|
// Either remove an icon by replacing them with nothing, or use the cached one since
|
||||||
matchingPref.setIcon(DEFAULT_ICON);
|
// there is a delay in fetching the injected icon, and we don't want an inappropriate
|
||||||
// Reserve room for the summary. This prevents the title from having to shift when the
|
// icon to be displayed while waiting for the injected icon.
|
||||||
// final title is injected.
|
final String iconUri =
|
||||||
matchingPref.setSummary(DEFAULT_SUMMARY);
|
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_ICON_URI, null);
|
||||||
|
Drawable drawable = DEFAULT_ICON;
|
||||||
|
if ((iconUri != null) && sIconCache.containsKey(iconUri)) {
|
||||||
|
Pair<String, Integer> icon = sIconCache.get(iconUri);
|
||||||
|
try {
|
||||||
|
drawable = context.getPackageManager()
|
||||||
|
.getResourcesForApplication(icon.first /* package name */)
|
||||||
|
.getDrawable(icon.second /* res id */,
|
||||||
|
context.getTheme());
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
// Ignore and just load the default icon.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matchingPref.setIcon(drawable);
|
||||||
|
// Either reserve room for the summary or load the cached one. This prevents the title
|
||||||
|
// from shifting when the final summary is injected.
|
||||||
|
final String summaryUri =
|
||||||
|
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, null);
|
||||||
|
String summary = DEFAULT_SUMMARY;
|
||||||
|
if ((summaryUri != null) && sSummaryCache.containsKey(summaryUri)) {
|
||||||
|
summary = sSummaryCache.get(summaryUri);
|
||||||
|
}
|
||||||
|
matchingPref.setSummary(summary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +144,9 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Check if the tile has content providers for dynamically updatable content.
|
// Check if the tile has content providers for dynamically updatable content.
|
||||||
String iconUri = tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_ICON_URI, null);
|
final String iconUri =
|
||||||
String summaryUri =
|
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_ICON_URI, null);
|
||||||
|
final String summaryUri =
|
||||||
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, null);
|
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, null);
|
||||||
if (!TextUtils.isEmpty(iconUri)) {
|
if (!TextUtils.isEmpty(iconUri)) {
|
||||||
String packageName = null;
|
String packageName = null;
|
||||||
@@ -131,6 +161,7 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
|
|||||||
Pair<String, Integer> icon =
|
Pair<String, Integer> icon =
|
||||||
TileUtils.getIconFromUri(context, packageName, iconUri, providerMap);
|
TileUtils.getIconFromUri(context, packageName, iconUri, providerMap);
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
|
sIconCache.put(iconUri, icon);
|
||||||
// Icon is only returned if the icon belongs to Settings or the target app.
|
// Icon is only returned if the icon belongs to Settings or the target app.
|
||||||
// setIcon must be called on the UI thread.
|
// setIcon must be called on the UI thread.
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||||
@@ -153,6 +184,7 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
|
|||||||
if (!TextUtils.isEmpty(summaryUri)) {
|
if (!TextUtils.isEmpty(summaryUri)) {
|
||||||
String summary = TileUtils.getTextFromUri(context, summaryUri, providerMap,
|
String summary = TileUtils.getTextFromUri(context, summaryUri, providerMap,
|
||||||
TileUtils.META_DATA_PREFERENCE_SUMMARY);
|
TileUtils.META_DATA_PREFERENCE_SUMMARY);
|
||||||
|
sSummaryCache.put(summaryUri, summary);
|
||||||
// setSummary must be called on UI thread.
|
// setSummary must be called on UI thread.
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@@ -77,7 +77,7 @@ public class SecurityFeatureProviderImplTest {
|
|||||||
private SecurityFeatureProviderImpl mImpl;
|
private SecurityFeatureProviderImpl mImpl;
|
||||||
|
|
||||||
@Implements(com.android.settingslib.drawer.TileUtils.class)
|
@Implements(com.android.settingslib.drawer.TileUtils.class)
|
||||||
public static class TileUtilsMock {
|
public static class ShadowTileUtils {
|
||||||
@Implementation
|
@Implementation
|
||||||
public static Pair getIconFromUri(Context context, String packageName, String uriString,
|
public static Pair getIconFromUri(Context context, String packageName, String uriString,
|
||||||
Map<String, IContentProvider> providerMap) {
|
Map<String, IContentProvider> providerMap) {
|
||||||
@@ -131,7 +131,7 @@ public class SecurityFeatureProviderImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Config(shadows = {
|
@Config(shadows = {
|
||||||
TileUtilsMock.class,
|
ShadowTileUtils.class,
|
||||||
})
|
})
|
||||||
public void updateTilesData_shouldUpdateMatchingPreference() {
|
public void updateTilesData_shouldUpdateMatchingPreference() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
@@ -151,7 +151,7 @@ public class SecurityFeatureProviderImplTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Config(shadows = {
|
@Config(shadows = {
|
||||||
TileUtilsMock.class,
|
ShadowTileUtils.class,
|
||||||
})
|
})
|
||||||
public void updateTilesData_shouldNotUpdateAlreadyUpdatedPreference() {
|
public void updateTilesData_shouldNotUpdateAlreadyUpdatedPreference() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
@@ -183,6 +183,31 @@ public class SecurityFeatureProviderImplTest {
|
|||||||
.setSummary(SecurityFeatureProviderImpl.DEFAULT_SUMMARY);
|
.setSummary(SecurityFeatureProviderImpl.DEFAULT_SUMMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(shadows = {
|
||||||
|
ShadowTileUtils.class,
|
||||||
|
})
|
||||||
|
public void initPreferences_shouldLoadCached() {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putString(TileUtils.META_DATA_PREFERENCE_ICON_URI, URI_GET_ICON);
|
||||||
|
bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY);
|
||||||
|
|
||||||
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
|
DashboardCategory dashboardCategory = getDashboardCategory();
|
||||||
|
dashboardCategory.getTile(0).metaData = bundle;
|
||||||
|
|
||||||
|
SecurityFeatureProviderImpl.sIconCache.put(
|
||||||
|
URI_GET_ICON,
|
||||||
|
ShadowTileUtils.getIconFromUri(null, null, null, null));
|
||||||
|
SecurityFeatureProviderImpl.sSummaryCache.put(
|
||||||
|
URI_GET_SUMMARY,
|
||||||
|
MOCK_SUMMARY);
|
||||||
|
|
||||||
|
mImpl.initPreferences(mContext, screen, dashboardCategory);
|
||||||
|
verify(screen.findPreference(MOCK_KEY)).setIcon(mMockDrawable);
|
||||||
|
verify(screen.findPreference(MOCK_KEY)).setSummary(MOCK_SUMMARY);
|
||||||
|
}
|
||||||
|
|
||||||
private PreferenceScreen getPreferenceScreen() {
|
private PreferenceScreen getPreferenceScreen() {
|
||||||
final PreferenceScreen screen = mock(PreferenceScreen.class);
|
final PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||||
final Preference pref = mock(Preference.class);
|
final Preference pref = mock(Preference.class);
|
||||||
|
Reference in New Issue
Block a user