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:
William Luh
2017-03-16 10:05:04 -07:00
parent 0ef2a55b08
commit 45f4e1241d
2 changed files with 67 additions and 10 deletions

View File

@@ -39,6 +39,7 @@ import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
import java.util.concurrent.Executors;
import java.util.TreeMap;
import java.util.Map;
/** Implementation for {@code SecurityFeatureProvider}. */
@@ -51,6 +52,12 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
@VisibleForTesting
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. */
public void updatePreferences(final Context context, final PreferenceScreen preferenceScreen,
final DashboardCategory dashboardCategory) {
@@ -89,11 +96,33 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
if (matchingPref == null) {
continue;
}
// Remove any icons that may be loaded before we inject the final icon.
matchingPref.setIcon(DEFAULT_ICON);
// Reserve room for the summary. This prevents the title from having to shift when the
// final title is injected.
matchingPref.setSummary(DEFAULT_SUMMARY);
// Either remove an icon by replacing them with nothing, or use the cached one since
// there is a delay in fetching the injected icon, and we don't want an inappropriate
// icon to be displayed while waiting for the injected icon.
final String iconUri =
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;
}
// Check if the tile has content providers for dynamically updatable content.
String iconUri = tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_ICON_URI, null);
String summaryUri =
final String iconUri =
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_ICON_URI, null);
final String summaryUri =
tile.metaData.getString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, null);
if (!TextUtils.isEmpty(iconUri)) {
String packageName = null;
@@ -131,6 +161,7 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
Pair<String, Integer> icon =
TileUtils.getIconFromUri(context, packageName, iconUri, providerMap);
if (icon != null) {
sIconCache.put(iconUri, icon);
// Icon is only returned if the icon belongs to Settings or the target app.
// setIcon must be called on the UI thread.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@@ -153,6 +184,7 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
if (!TextUtils.isEmpty(summaryUri)) {
String summary = TileUtils.getTextFromUri(context, summaryUri, providerMap,
TileUtils.META_DATA_PREFERENCE_SUMMARY);
sSummaryCache.put(summaryUri, summary);
// setSummary must be called on UI thread.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override