Fix race condition and optimize categoryUpdater refresh
- In SettingsActivity, do not call updateCategories() if nothing
changed.
- In SummaryLoader, create a mapping between tile key and summary. This
is necessary to handle a race condition where category is refreshed
after summary load.
- In DashboardSummary, refresh Tile's summary to latest cache value
everytime category is refreshed.
Change-Id: I61389b8ba614ba7e34939325bada6e1bd6fa6709
Fix: 63149109
Test: robotests
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 556dbfb..a7d9afc 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -45,7 +45,6 @@
import android.text.TextUtils;
import android.transition.TransitionManager;
import android.util.Log;
-import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@@ -64,7 +63,6 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DynamicIndexableContentMonitor;
import com.android.settings.search.SearchActivity;
-import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.drawer.DashboardCategory;
@@ -770,68 +768,81 @@
PackageManager pm = getPackageManager();
final UserManager um = UserManager.get(this);
final boolean isAdmin = um.isAdminUser();
-
+ boolean somethingChanged = false;
String packageName = getPackageName();
- setTileEnabled(new ComponentName(packageName, WifiSettingsActivity.class.getName()),
- pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin);
+ somethingChanged = setTileEnabled(
+ new ComponentName(packageName, WifiSettingsActivity.class.getName()),
+ pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin) || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.BluetoothSettingsActivity.class.getName()),
- pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin);
+ pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DataUsageSummaryActivity.class.getName()),
- Utils.isBandwidthControlEnabled(), isAdmin);
+ Utils.isBandwidthControlEnabled(), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.SimSettingsActivity.class.getName()),
- Utils.showSimCardTile(this), isAdmin);
+ Utils.showSimCardTile(this), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.PowerUsageSummaryActivity.class.getName()),
- mBatteryPresent, isAdmin);
+ mBatteryPresent, isAdmin) || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.UserSettingsActivity.class.getName()),
UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
- && !Utils.isMonkeyRunning(), isAdmin);
+ && !Utils.isMonkeyRunning(), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.NetworkDashboardActivity.class.getName()),
- !UserManager.isDeviceInDemoMode(this), isAdmin);
+ !UserManager.isDeviceInDemoMode(this), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.ConnectedDeviceDashboardActivity.class.getName()),
- !UserManager.isDeviceInDemoMode(this), isAdmin);
+ !UserManager.isDeviceInDemoMode(this), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DateTimeSettingsActivity.class.getName()),
- !UserManager.isDeviceInDemoMode(this), isAdmin);
+ !UserManager.isDeviceInDemoMode(this), isAdmin)
+ || somethingChanged;
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.PaymentSettingsActivity.class.getName()),
pm.hasSystemFeature(PackageManager.FEATURE_NFC)
&& pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
- && adapter != null && adapter.isEnabled(), isAdmin);
+ && adapter != null && adapter.isEnabled(), isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.PrintSettingsActivity.class.getName()),
- pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin);
+ pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin)
+ || somethingChanged;
final boolean showDev = mDevelopmentPreferences.getBoolean(
DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng"))
&& !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DevelopmentSettingsActivity.class.getName()),
- showDev, isAdmin);
+ showDev, isAdmin)
+ || somethingChanged;
// Enable/disable backup settings depending on whether the user is admin.
- setTileEnabled(new ComponentName(packageName,
- BackupSettingsActivity.class.getName()), true, isAdmin);
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
+ BackupSettingsActivity.class.getName()), true, isAdmin)
+ || somethingChanged;
- setTileEnabled(new ComponentName(packageName,
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.WifiDisplaySettingsActivity.class.getName()),
- WifiDisplaySettings.isAvailable(this), isAdmin);
+ WifiDisplaySettings.isAvailable(this), isAdmin)
+ || somethingChanged;
if (UserHandle.MU_ENABLED && !isAdmin) {
@@ -848,7 +859,8 @@
SettingsGateway.SETTINGS_FOR_RESTRICTED, name);
if (packageName.equals(component.getPackageName())
&& !isEnabledForRestricted) {
- setTileEnabled(component, false, isAdmin);
+ somethingChanged = setTileEnabled(component, false, isAdmin)
+ || somethingChanged;
}
}
}
@@ -856,16 +868,24 @@
}
// Final step, refresh categories.
- updateCategories();
+ if (somethingChanged) {
+ Log.d(LOG_TAG, "Enabled state changed for some tiles, reloading all categories");
+ updateCategories();
+ } else {
+ Log.d(LOG_TAG, "No enabled state changed, skipping updateCategory call");
+ }
}
- private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin) {
+ /**
+ * @return whether or not the enabled state actually changed.
+ */
+ private boolean setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin) {
if (UserHandle.MU_ENABLED && !isAdmin && getPackageName().equals(component.getPackageName())
&& !ArrayUtils.contains(SettingsGateway.SETTINGS_FOR_RESTRICTED,
component.getClassName())) {
enabled = false;
}
- setTileEnabled(component, enabled);
+ return setTileEnabled(component, enabled);
}
private void getMetaData() {
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 71a4d8f..ae99106 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -294,10 +294,12 @@
final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(
CategoryKey.CATEGORY_HOMEPAGE);
+ mSummaryLoader.updateSummaryToCache(category);
if (suggestions != null) {
mAdapter.setCategoriesAndSuggestions(category, suggestions);
} else {
mAdapter.setCategory(category);
}
}
+
}
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index df21168..4586a55 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -34,7 +34,6 @@
import com.android.settings.SettingsActivity;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.drawer.DashboardCategory;
-import com.android.settingslib.drawer.SettingsDrawerActivity;
import com.android.settingslib.drawer.Tile;
import java.lang.reflect.Field;
@@ -47,7 +46,8 @@
public static final String SUMMARY_PROVIDER_FACTORY = "SUMMARY_PROVIDER_FACTORY";
private final Activity mActivity;
- private final ArrayMap<SummaryProvider, ComponentName> mSummaryMap = new ArrayMap<>();
+ private final ArrayMap<SummaryProvider, ComponentName> mSummaryProviderMap = new ArrayMap<>();
+ private final ArrayMap<String, CharSequence> mSummaryTextMap = new ArrayMap<>();
private final DashboardFeatureProvider mDashboardFeatureProvider;
private final String mCategoryKey;
@@ -111,13 +111,13 @@
}
public void setSummary(SummaryProvider provider, final CharSequence summary) {
- final ComponentName component = mSummaryMap.get(provider);
+ final ComponentName component = mSummaryProviderMap.get(provider);
mHandler.post(new Runnable() {
@Override
public void run() {
final Tile tile = getTileFromCategory(
- mDashboardFeatureProvider.getTilesForCategory(mCategoryKey), component);
+ mDashboardFeatureProvider.getTilesForCategory(mCategoryKey), component);
if (tile == null) {
if (DEBUG) {
@@ -142,6 +142,7 @@
}
return;
}
+ mSummaryTextMap.put(mDashboardFeatureProvider.getDashboardKeyForTile(tile), summary);
tile.summary = summary;
if (mSummaryConsumer != null) {
mSummaryConsumer.notifySummaryChanged(tile);
@@ -223,11 +224,27 @@
});
}
+ /**
+ * Updates all tile's summary to latest cached version. This is necessary to handle the case
+ * where category is updated after summary change.
+ */
+ public void updateSummaryToCache(DashboardCategory category) {
+ if (category == null) {
+ return;
+ }
+ for (Tile tile : category.tiles) {
+ final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
+ if (mSummaryTextMap.containsKey(key)) {
+ tile.summary = mSummaryTextMap.get(key);
+ }
+ }
+ }
+
private synchronized void setListeningW(boolean listening) {
if (mWorkerListening == listening) return;
mWorkerListening = listening;
if (DEBUG) Log.d(TAG, "Listening " + listening);
- for (SummaryProvider p : mSummaryMap.keySet()) {
+ for (SummaryProvider p : mSummaryProviderMap.keySet()) {
try {
p.setListening(listening);
} catch (Exception e) {
@@ -240,28 +257,10 @@
SummaryProvider provider = getSummaryProvider(tile);
if (provider != null) {
if (DEBUG) Log.d(TAG, "Creating " + tile);
- mSummaryMap.put(provider, tile.intent.getComponent());
+ mSummaryProviderMap.put(provider, tile.intent.getComponent());
}
}
- private Tile getTileFromCategory(List<DashboardCategory> categories, ComponentName component) {
- if (categories == null) {
- if (DEBUG) {
- Log.d(TAG, "Category is null, can't find tile");
- }
- return null;
- }
- final int categorySize = categories.size();
- for (int i = 0; i < categorySize; i++) {
- final DashboardCategory category = categories.get(i);
- final Tile tile = getTileFromCategory(category, component);
- if (tile != null) {
- return tile;
- }
- }
- return null;
- }
-
private Tile getTileFromCategory(DashboardCategory category, ComponentName component) {
if (category == null || category.tiles == null) {
return null;
@@ -276,6 +275,8 @@
return null;
}
+
+
public interface SummaryProvider {
void setListening(boolean listening);
}