Remove summary provider
- use SummaryProvider to provide the summary of UserSettings - use WifiDisplayPreferenceController to replace the summary loader in WifiDisplaySettings - use ConfigureNotificationPreferernceController to replace the sumary load in ConfigureNotificationSettings Fixes: 141653158 Test: robolectric Change-Id: Id5f5ed645707caa0b25ecae5252174cbf017651c
This commit is contained in:
@@ -37,12 +37,12 @@ import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.PreferenceControllerListHelper;
|
||||
import com.android.settings.core.SettingsBaseActivity;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.search.Indexable;
|
||||
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.Tile;
|
||||
import com.android.settingslib.search.Indexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -56,7 +56,7 @@ import java.util.Set;
|
||||
*/
|
||||
public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
implements SettingsBaseActivity.CategoryListener, Indexable,
|
||||
SummaryLoader.SummaryConsumer, PreferenceGroup.OnExpandButtonClickListener,
|
||||
PreferenceGroup.OnExpandButtonClickListener,
|
||||
BasePreferenceController.UiBlockListener {
|
||||
private static final String TAG = "DashboardFragment";
|
||||
|
||||
@@ -68,7 +68,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
private DashboardFeatureProvider mDashboardFeatureProvider;
|
||||
private DashboardTilePlaceholderPreferenceController mPlaceholderPreferenceController;
|
||||
private boolean mListeningToCategoryChange;
|
||||
private SummaryLoader mSummaryLoader;
|
||||
private List<String> mSuppressInjectedTileKeys;
|
||||
@VisibleForTesting
|
||||
UiBlockerController mBlockerController;
|
||||
@@ -128,7 +127,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
|
||||
if (!keys.isEmpty()) {
|
||||
mBlockerController = new UiBlockerController(keys);
|
||||
mBlockerController.start(()->updatePreferenceVisibility(mPreferenceControllers));
|
||||
mBlockerController.start(() -> updatePreferenceVisibility(mPreferenceControllers));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,10 +168,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
if (category == null) {
|
||||
return;
|
||||
}
|
||||
if (mSummaryLoader != null) {
|
||||
// SummaryLoader can be null when there is no dynamic tiles.
|
||||
mSummaryLoader.setListening(true);
|
||||
}
|
||||
final Activity activity = getActivity();
|
||||
if (activity instanceof SettingsBaseActivity) {
|
||||
mListeningToCategoryChange = true;
|
||||
@@ -180,19 +175,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySummaryChanged(Tile tile) {
|
||||
final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
|
||||
final Preference pref = getPreferenceScreen().findPreference(key);
|
||||
if (pref == null) {
|
||||
Log.d(getLogTag(), String.format(
|
||||
"Can't find pref by key %s, skipping update summary %s",
|
||||
key, tile.getDescription()));
|
||||
return;
|
||||
}
|
||||
pref.setSummary(tile.getSummary(pref.getContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@@ -220,10 +202,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (mSummaryLoader != null) {
|
||||
// SummaryLoader can be null when there is no dynamic tiles.
|
||||
mSummaryLoader.setListening(false);
|
||||
}
|
||||
if (mListeningToCategoryChange) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity instanceof SettingsBaseActivity) {
|
||||
@@ -413,13 +391,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
// Create a list to track which tiles are to be removed.
|
||||
final List<String> remove = new ArrayList<>(mDashboardTilePrefKeys);
|
||||
|
||||
// There are dashboard tiles, so we need to install SummaryLoader.
|
||||
if (mSummaryLoader != null) {
|
||||
mSummaryLoader.release();
|
||||
}
|
||||
final Context context = getContext();
|
||||
mSummaryLoader = new SummaryLoader(getActivity(), getCategoryKey());
|
||||
mSummaryLoader.setSummaryConsumer(this);
|
||||
// Install dashboard tiles.
|
||||
final boolean forceRoundedIcons = shouldForceRoundedIcon();
|
||||
for (Tile tile : tiles) {
|
||||
@@ -456,7 +427,6 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
|
||||
screen.removePreference(preference);
|
||||
}
|
||||
}
|
||||
mSummaryLoader.setListening(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.dashboard;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
public class SummaryLoader {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "SummaryLoader";
|
||||
|
||||
public static final String SUMMARY_PROVIDER_FACTORY = "SUMMARY_PROVIDER_FACTORY";
|
||||
|
||||
private final Activity mActivity;
|
||||
private final ArrayMap<SummaryProvider, ComponentName> mSummaryProviderMap = new ArrayMap<>();
|
||||
private final ArrayMap<String, CharSequence> mSummaryTextMap = new ArrayMap<>();
|
||||
private final DashboardFeatureProvider mDashboardFeatureProvider;
|
||||
private final String mCategoryKey;
|
||||
|
||||
private final Worker mWorker;
|
||||
private final HandlerThread mWorkerThread;
|
||||
|
||||
private SummaryConsumer mSummaryConsumer;
|
||||
private boolean mListening;
|
||||
private boolean mWorkerListening;
|
||||
private ArraySet<BroadcastReceiver> mReceivers = new ArraySet<>();
|
||||
|
||||
public SummaryLoader(Activity activity, String categoryKey) {
|
||||
mDashboardFeatureProvider = FeatureFactory.getFactory(activity)
|
||||
.getDashboardFeatureProvider(activity);
|
||||
mCategoryKey = categoryKey;
|
||||
mWorkerThread = new HandlerThread("SummaryLoader", Process.THREAD_PRIORITY_BACKGROUND);
|
||||
mWorkerThread.start();
|
||||
mWorker = new Worker(mWorkerThread.getLooper());
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mWorkerThread.quitSafely();
|
||||
// Make sure we aren't listening.
|
||||
setListeningW(false);
|
||||
}
|
||||
|
||||
public void setSummaryConsumer(SummaryConsumer summaryConsumer) {
|
||||
mSummaryConsumer = summaryConsumer;
|
||||
}
|
||||
|
||||
public void setSummary(SummaryProvider provider, final CharSequence summary) {
|
||||
final ComponentName component = mSummaryProviderMap.get(provider);
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
|
||||
final Tile tile = getTileFromCategory(
|
||||
mDashboardFeatureProvider.getTilesForCategory(mCategoryKey), component);
|
||||
|
||||
if (tile == null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Can't find tile for " + component);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "setSummary " + tile.getDescription() + " - " + summary);
|
||||
}
|
||||
|
||||
updateSummaryIfNeeded(mActivity.getApplicationContext(), tile, summary);
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateSummaryIfNeeded(Context context, Tile tile, CharSequence summary) {
|
||||
if (TextUtils.equals(tile.getSummary(context), summary)) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Summary doesn't change, skipping summary update for "
|
||||
+ tile.getDescription());
|
||||
}
|
||||
return;
|
||||
}
|
||||
mSummaryTextMap.put(mDashboardFeatureProvider.getDashboardKeyForTile(tile), summary);
|
||||
tile.overrideSummary(summary);
|
||||
if (mSummaryConsumer != null) {
|
||||
mSummaryConsumer.notifySummaryChanged(tile);
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "SummaryConsumer is null, skipping summary update for "
|
||||
+ tile.getDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only call from the main thread.
|
||||
*/
|
||||
public void setListening(boolean listening) {
|
||||
if (mListening == listening) {
|
||||
return;
|
||||
}
|
||||
mListening = listening;
|
||||
// Unregister listeners immediately.
|
||||
for (int i = 0; i < mReceivers.size(); i++) {
|
||||
mActivity.unregisterReceiver(mReceivers.valueAt(i));
|
||||
}
|
||||
mReceivers.clear();
|
||||
|
||||
mWorker.removeMessages(Worker.MSG_SET_LISTENING);
|
||||
if (!listening) {
|
||||
// Stop listen
|
||||
mWorker.obtainMessage(Worker.MSG_SET_LISTENING, 0 /* listening */).sendToTarget();
|
||||
} else {
|
||||
// Start listen
|
||||
if (mSummaryProviderMap.isEmpty()) {
|
||||
// Category not initialized yet, init before starting to listen
|
||||
if (!mWorker.hasMessages(Worker.MSG_GET_CATEGORY_TILES_AND_SET_LISTENING)) {
|
||||
mWorker.sendEmptyMessage(Worker.MSG_GET_CATEGORY_TILES_AND_SET_LISTENING);
|
||||
}
|
||||
} else {
|
||||
// Category already initialized, start listening immediately
|
||||
mWorker.obtainMessage(Worker.MSG_SET_LISTENING, 1 /* listening */).sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SummaryProvider getSummaryProvider(Tile tile) {
|
||||
if (!mActivity.getPackageName().equals(tile.getPackageName())) {
|
||||
// Not within Settings, can't load Summary directly.
|
||||
// TODO: Load summary indirectly.
|
||||
return null;
|
||||
}
|
||||
final Bundle metaData = tile.getMetaData();
|
||||
final Intent intent = tile.getIntent();
|
||||
if (metaData == null) {
|
||||
Log.d(TAG, "No metadata specified for " + intent.getComponent());
|
||||
return null;
|
||||
}
|
||||
final String clsName = metaData.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);
|
||||
if (clsName == null) {
|
||||
Log.d(TAG, "No fragment specified for " + intent.getComponent());
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Class<?> cls = Class.forName(clsName);
|
||||
Field field = cls.getField(SUMMARY_PROVIDER_FACTORY);
|
||||
SummaryProviderFactory factory = (SummaryProviderFactory) field.get(null);
|
||||
return factory.createSummaryProvider(mActivity, this);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (DEBUG) Log.d(TAG, "Couldn't find " + clsName, e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
if (DEBUG) Log.d(TAG, "Couldn't find " + SUMMARY_PROVIDER_FACTORY, e);
|
||||
} catch (ClassCastException e) {
|
||||
if (DEBUG) Log.d(TAG, "Couldn't cast " + SUMMARY_PROVIDER_FACTORY, e);
|
||||
} catch (IllegalAccessException e) {
|
||||
if (DEBUG) Log.d(TAG, "Couldn't get " + SUMMARY_PROVIDER_FACTORY, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a receiver and automatically unregisters it when the activity is stopping.
|
||||
* This ensures that the receivers are unregistered immediately, since most summary loader
|
||||
* operations are asynchronous.
|
||||
*/
|
||||
public void registerReceiver(final BroadcastReceiver receiver, final IntentFilter filter) {
|
||||
mActivity.runOnUiThread(() -> {
|
||||
if (!mListening) {
|
||||
return;
|
||||
}
|
||||
mReceivers.add(receiver);
|
||||
mActivity.registerReceiver(receiver, filter);
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized void setListeningW(boolean listening) {
|
||||
if (mWorkerListening == listening) {
|
||||
return;
|
||||
}
|
||||
mWorkerListening = listening;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Listening " + listening);
|
||||
}
|
||||
for (SummaryProvider p : mSummaryProviderMap.keySet()) {
|
||||
try {
|
||||
p.setListening(listening);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "Problem in setListening", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void makeProviderW(Tile tile) {
|
||||
SummaryProvider provider = getSummaryProvider(tile);
|
||||
if (provider != null) {
|
||||
if (DEBUG) Log.d(TAG, "Creating " + tile);
|
||||
mSummaryProviderMap.put(provider, tile.getIntent().getComponent());
|
||||
}
|
||||
}
|
||||
|
||||
private Tile getTileFromCategory(DashboardCategory category, ComponentName component) {
|
||||
if (category == null || category.getTilesCount() == 0) {
|
||||
return null;
|
||||
}
|
||||
final List<Tile> tiles = category.getTiles();
|
||||
final int tileCount = tiles.size();
|
||||
for (int j = 0; j < tileCount; j++) {
|
||||
final Tile tile = tiles.get(j);
|
||||
if (component.equals(tile.getIntent().getComponent())) {
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public interface SummaryProvider {
|
||||
void setListening(boolean listening);
|
||||
}
|
||||
|
||||
public interface SummaryConsumer {
|
||||
void notifySummaryChanged(Tile tile);
|
||||
}
|
||||
|
||||
public interface SummaryProviderFactory {
|
||||
SummaryProvider createSummaryProvider(Activity activity, SummaryLoader summaryLoader);
|
||||
}
|
||||
|
||||
private class Worker extends Handler {
|
||||
private static final int MSG_GET_CATEGORY_TILES_AND_SET_LISTENING = 1;
|
||||
private static final int MSG_GET_PROVIDER = 2;
|
||||
private static final int MSG_SET_LISTENING = 3;
|
||||
|
||||
public Worker(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_GET_CATEGORY_TILES_AND_SET_LISTENING:
|
||||
final DashboardCategory category =
|
||||
mDashboardFeatureProvider.getTilesForCategory(mCategoryKey);
|
||||
if (category == null || category.getTilesCount() == 0) {
|
||||
return;
|
||||
}
|
||||
final List<Tile> tiles = category.getTiles();
|
||||
for (Tile tile : tiles) {
|
||||
makeProviderW(tile);
|
||||
}
|
||||
setListeningW(true);
|
||||
break;
|
||||
case MSG_GET_PROVIDER:
|
||||
Tile tile = (Tile) msg.obj;
|
||||
makeProviderW(tile);
|
||||
break;
|
||||
case MSG_SET_LISTENING:
|
||||
boolean listening = msg.obj != null && msg.obj.equals(1);
|
||||
setListeningW(listening);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
91
src/com/android/settings/dashboard/SummaryProvider.java
Normal file
91
src/com/android/settings/dashboard/SummaryProvider.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* 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
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard;
|
||||
|
||||
import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.backup.BackupSettingsHelper;
|
||||
|
||||
/** Provide preference summary for injected items. */
|
||||
public class SummaryProvider extends ContentProvider {
|
||||
private static final String BACKUP = "backup";
|
||||
private static final String USER = "user";
|
||||
|
||||
@Override
|
||||
public Bundle call(String method, String uri, Bundle extras) {
|
||||
final Bundle bundle = new Bundle();
|
||||
switch (method) {
|
||||
case BACKUP:
|
||||
bundle.putString(META_DATA_PREFERENCE_SUMMARY,
|
||||
new BackupSettingsHelper(getContext()).getSummary());
|
||||
break;
|
||||
case USER:
|
||||
final Context context = getContext();
|
||||
final UserInfo info = context.getSystemService(UserManager.class).getUserInfo(
|
||||
UserHandle.myUserId());
|
||||
bundle.putString(META_DATA_PREFERENCE_SUMMARY,
|
||||
context.getString(R.string.users_summary,
|
||||
info.name));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown Uri format: " + uri);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
|
||||
String sortOrder) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType(Uri uri) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri insert(Uri uri, ContentValues values) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user