[Settings] Support pure switch of inline toggle of Settings Injection v2

Bug: 132808482
Test: robotest
Change-Id: Ib24614fb46fe990925edad721e3b7d5d032854fc
This commit is contained in:
Jason Chiu
2019-10-24 17:30:34 +08:00
parent 9096329b22
commit bac5987c8e
12 changed files with 664 additions and 262 deletions

View File

@@ -17,11 +17,11 @@ package com.android.settings.dashboard;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.CallSuper;
@@ -30,6 +30,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -41,6 +42,7 @@ import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.ProviderTile;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.search.Indexable;
@@ -49,7 +51,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Objects;
/**
* Base fragment for dashboard style UI containing a list of static and dynamic setting items.
@@ -60,9 +62,11 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
BasePreferenceController.UiBlockListener {
private static final String TAG = "DashboardFragment";
@VisibleForTesting
final ArrayMap<String, List<DynamicDataObserver>> mDashboardTilePrefKeys = new ArrayMap<>();
private final Map<Class, List<AbstractPreferenceController>> mPreferenceControllers =
new ArrayMap<>();
private final Set<String> mDashboardTilePrefKeys = new ArraySet<>();
private final List<DynamicDataObserver> mRegisteredObservers = new ArrayList<>();
private final List<AbstractPreferenceController> mControllers = new ArrayList<>();
private DashboardFeatureProvider mDashboardFeatureProvider;
@@ -171,6 +175,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
mListeningToCategoryChange = true;
((SettingsBaseActivity) activity).addCategoryListener(this);
}
final ContentResolver resolver = getContentResolver();
mDashboardTilePrefKeys.values().stream()
.filter(Objects::nonNull)
.flatMap(List::stream)
.forEach(observer -> {
if (!mRegisteredObservers.contains(observer)) {
registerDynamicDataObserver(resolver, observer);
}
});
}
@Override
@@ -200,6 +213,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
@Override
public void onStop() {
super.onStop();
unregisterDynamicDataObservers(new ArrayList<>(mRegisteredObservers));
if (mListeningToCategoryChange) {
final Activity activity = getActivity();
if (activity instanceof SettingsBaseActivity) {
@@ -325,7 +339,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
* Refresh all preference items, including both static prefs from xml, and dynamic items from
* DashboardCategory.
*/
private void refreshAllPreferences(final String TAG) {
private void refreshAllPreferences(final String tag) {
final PreferenceScreen screen = getPreferenceScreen();
// First remove old preferences.
if (screen != null) {
@@ -336,11 +350,11 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
// Add resource based tiles.
displayResourceTiles();
refreshDashboardTiles(TAG);
refreshDashboardTiles(tag);
final Activity activity = getActivity();
if (activity != null) {
Log.d(TAG, "All preferences added, reporting fully drawn");
Log.d(tag, "All preferences added, reporting fully drawn");
activity.reportFullyDrawn();
}
@@ -371,59 +385,62 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
/**
* Refresh preference items backed by DashboardCategory.
*/
@VisibleForTesting
void refreshDashboardTiles(final String TAG) {
private void refreshDashboardTiles(final String tag) {
final PreferenceScreen screen = getPreferenceScreen();
final DashboardCategory category =
mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());
if (category == null) {
Log.d(TAG, "NO dashboard tiles for " + TAG);
Log.d(tag, "NO dashboard tiles for " + tag);
return;
}
final List<Tile> tiles = category.getTiles();
if (tiles == null) {
Log.d(TAG, "tile list is empty, skipping category " + category.key);
Log.d(tag, "tile list is empty, skipping category " + category.key);
return;
}
// Create a list to track which tiles are to be removed.
final List<String> remove = new ArrayList<>(mDashboardTilePrefKeys);
final Map<String, List<DynamicDataObserver>> remove = new ArrayMap(mDashboardTilePrefKeys);
// Install dashboard tiles.
final boolean forceRoundedIcons = shouldForceRoundedIcon();
for (Tile tile : tiles) {
final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
if (TextUtils.isEmpty(key)) {
Log.d(TAG, "tile does not contain a key, skipping " + tile);
Log.d(tag, "tile does not contain a key, skipping " + tile);
continue;
}
if (!displayTile(tile)) {
continue;
}
if (mDashboardTilePrefKeys.contains(key)) {
if (mDashboardTilePrefKeys.containsKey(key)) {
// Have the key already, will rebind.
final Preference preference = screen.findPreference(key);
mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), forceRoundedIcons,
getMetricsCategory(), preference, tile, key,
mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(getActivity(),
forceRoundedIcons, getMetricsCategory(), preference, tile, key,
mPlaceholderPreferenceController.getOrder());
} else {
// Don't have this key, add it.
final Preference pref = new Preference(getPrefContext());
mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), forceRoundedIcons,
getMetricsCategory(), pref, tile, key,
mPlaceholderPreferenceController.getOrder());
final Preference pref = createPreference(tile);
final List<DynamicDataObserver> observers =
mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(getActivity(),
forceRoundedIcons, getMetricsCategory(), pref, tile, key,
mPlaceholderPreferenceController.getOrder());
screen.addPreference(pref);
mDashboardTilePrefKeys.add(key);
registerDynamicDataObservers(observers);
mDashboardTilePrefKeys.put(key, observers);
}
remove.remove(key);
}
// Finally remove tiles that are gone.
for (String key : remove) {
for (Map.Entry<String, List<DynamicDataObserver>> entry : remove.entrySet()) {
final String key = entry.getKey();
mDashboardTilePrefKeys.remove(key);
final Preference preference = screen.findPreference(key);
if (preference != null) {
screen.removePreference(preference);
}
unregisterDynamicDataObservers(entry.getValue());
}
}
@@ -431,4 +448,41 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
public void onBlockerWorkFinished(BasePreferenceController controller) {
mBlockerController.countDown(controller.getPreferenceKey());
}
@VisibleForTesting
Preference createPreference(Tile tile) {
return tile instanceof ProviderTile
? new SwitchPreference(getPrefContext())
: new Preference(getPrefContext());
}
@VisibleForTesting
void registerDynamicDataObservers(List<DynamicDataObserver> observers) {
if (observers == null || observers.isEmpty()) {
return;
}
final ContentResolver resolver = getContentResolver();
observers.forEach(observer -> registerDynamicDataObserver(resolver, observer));
}
private void registerDynamicDataObserver(ContentResolver resolver,
DynamicDataObserver observer) {
Log.d(TAG, "register observer: @" + Integer.toHexString(observer.hashCode())
+ ", uri: " + observer.getUri());
resolver.registerContentObserver(observer.getUri(), false, observer);
mRegisteredObservers.add(observer);
}
private void unregisterDynamicDataObservers(List<DynamicDataObserver> observers) {
if (observers == null || observers.isEmpty()) {
return;
}
final ContentResolver resolver = getContentResolver();
observers.forEach(observer -> {
Log.d(TAG, "unregister observer: @" + Integer.toHexString(observer.hashCode())
+ ", uri: " + observer.getUri());
mRegisteredObservers.remove(observer);
resolver.unregisterContentObserver(observer);
});
}
}