Loading src/com/android/settings/core/SettingsBaseActivity.java +79 −13 Original line number Diff line number Diff line Loading @@ -41,11 +41,14 @@ import androidx.fragment.app.FragmentActivity; import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.dashboard.CategoryManager; import com.android.settingslib.drawer.Tile; import com.google.android.setupcompat.util.WizardManagerHelper; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; public class SettingsBaseActivity extends FragmentActivity { Loading @@ -59,6 +62,7 @@ public class SettingsBaseActivity extends FragmentActivity { private final PackageReceiver mPackageReceiver = new PackageReceiver(); private final List<CategoryListener> mCategoryListeners = new ArrayList<>(); private int mCategoriesUpdateTaskCount; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { Loading Loading @@ -147,10 +151,10 @@ public class SettingsBaseActivity extends FragmentActivity { ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params); } private void onCategoriesChanged() { private void onCategoriesChanged(Set<String> categories) { final int N = mCategoryListeners.size(); for (int i = 0; i < N; i++) { mCategoryListeners.get(i).onCategoriesChanged(); mCategoryListeners.get(i).onCategoriesChanged(categories); } } Loading Loading @@ -194,38 +198,100 @@ public class SettingsBaseActivity extends FragmentActivity { * Updates dashboard categories. Only necessary to call this after setTileEnabled */ public void updateCategories() { new CategoriesUpdateTask().execute(); updateCategories(false /* fromBroadcast */); } private void updateCategories(boolean fromBroadcast) { // Only allow at most 2 tasks existing at the same time since when the first one is // executing, there may be new data from the second update request. // Ignore the third update request because the second task is still waiting for the first // task to complete in a serial thread, which will get the latest data. if (mCategoriesUpdateTaskCount < 2) { new CategoriesUpdateTask().execute(fromBroadcast); } } public interface CategoryListener { void onCategoriesChanged(); /** * @param categories the changed categories that have to be refreshed, or null to force * refreshing all. */ void onCategoriesChanged(@Nullable Set<String> categories); } private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> { private class CategoriesUpdateTask extends AsyncTask<Boolean, Void, Set<String>> { private final Context mContext; private final CategoryManager mCategoryManager; private Map<ComponentName, Tile> mPreviousTileMap; public CategoriesUpdateTask() { mCategoryManager = CategoryManager.get(SettingsBaseActivity.this); mCategoriesUpdateTaskCount++; mContext = SettingsBaseActivity.this; mCategoryManager = CategoryManager.get(mContext); } @Override protected Void doInBackground(Void... params) { mCategoryManager.reloadAllCategories(SettingsBaseActivity.this); return null; protected Set<String> doInBackground(Boolean... params) { mPreviousTileMap = mCategoryManager.getTileByComponentMap(); mCategoryManager.reloadAllCategories(mContext); mCategoryManager.updateCategoryFromDenylist(sTileDenylist); return getChangedCategories(params[0]); } @Override protected void onPostExecute(Void result) { mCategoryManager.updateCategoryFromDenylist(sTileDenylist); onCategoriesChanged(); protected void onPostExecute(Set<String> categories) { if (categories == null || !categories.isEmpty()) { onCategoriesChanged(categories); } mCategoriesUpdateTaskCount--; } // Return the changed categories that have to be refreshed, or null to force refreshing all. private Set<String> getChangedCategories(boolean fromBroadcast) { if (!fromBroadcast) { // Always refresh for non-broadcast case. return null; } final Set<String> changedCategories = new ArraySet<>(); final Map<ComponentName, Tile> currentTileMap = mCategoryManager.getTileByComponentMap(); currentTileMap.forEach((component, currentTile) -> { final Tile previousTile = mPreviousTileMap.get(component); // Check if the tile is newly added. if (previousTile == null) { Log.i(TAG, "Tile added: " + component.flattenToShortString()); changedCategories.add(currentTile.getCategory()); return; } // Check if the title or summary has changed. if (!TextUtils.equals(currentTile.getTitle(mContext), previousTile.getTitle(mContext)) || !TextUtils.equals(currentTile.getSummary(mContext), previousTile.getSummary(mContext))) { Log.i(TAG, "Tile changed: " + component.flattenToShortString()); changedCategories.add(currentTile.getCategory()); } }); // Check if any previous tile is removed. final Set<ComponentName> removal = new ArraySet(mPreviousTileMap.keySet()); removal.removeAll(currentTileMap.keySet()); removal.forEach(component -> { Log.i(TAG, "Tile removed: " + component.flattenToShortString()); changedCategories.add(mPreviousTileMap.get(component).getCategory()); }); return changedCategories; } } private class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { updateCategories(); updateCategories(true /* fromBroadcast */); } } } src/com/android/settings/dashboard/CategoryManager.java +31 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import java.util.Set; public class CategoryManager { private static final String TAG = "CategoryManager"; private static final boolean DEBUG = false; private static CategoryManager sInstance; private final InterestingConfigChanges mInterestingConfigChanges; Loading Loading @@ -92,6 +93,7 @@ public class CategoryManager { public synchronized void updateCategoryFromDenylist(Set<ComponentName> tileDenylist) { if (mCategories == null) { Log.w(TAG, "Category is null, skipping denylist update"); return; } for (int i = 0; i < mCategories.size(); i++) { DashboardCategory category = mCategories.get(i); Loading @@ -104,6 +106,31 @@ public class CategoryManager { } } /** Return the current tile map */ public synchronized Map<ComponentName, Tile> getTileByComponentMap() { final Map<ComponentName, Tile> result = new ArrayMap<>(); if (mCategories == null) { Log.w(TAG, "Category is null, no tiles"); return result; } mCategories.forEach(category -> { for (int i = 0; i < category.getTilesCount(); i++) { final Tile tile = category.getTile(i); result.put(tile.getIntent().getComponent(), tile); } }); return result; } private void logTiles(Context context) { if (DEBUG) { getTileByComponentMap().forEach((component, tile) -> { Log.d(TAG, "Tile: " + tile.getCategory().replace("com.android.settings.", "") + ": " + tile.getTitle(context) + ", " + component.flattenToShortString()); }); } } private synchronized void tryInitCategories(Context context) { // Keep cached tiles by default. The cache is only invalidated when InterestingConfigChange // happens. Loading @@ -112,6 +139,7 @@ public class CategoryManager { private synchronized void tryInitCategories(Context context, boolean forceClearCache) { if (mCategories == null) { final boolean firstLoading = mCategoryByKeyMap.isEmpty(); if (forceClearCache) { mTileByComponentCache.clear(); } Loading @@ -123,6 +151,9 @@ public class CategoryManager { backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); sortCategories(context, mCategoryByKeyMap); filterDuplicateTiles(mCategoryByKeyMap); if (firstLoading) { logTiles(context); } } } Loading src/com/android/settings/dashboard/DashboardFragment.java +14 −5 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutionException; /** Loading Loading @@ -160,14 +161,22 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } @Override public void onCategoriesChanged() { final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(getCategoryKey()); if (category == null) { public void onCategoriesChanged(Set<String> categories) { final String categoryKey = getCategoryKey(); final DashboardCategory dashboardCategory = mDashboardFeatureProvider.getTilesForCategory(categoryKey); if (dashboardCategory == null) { return; } if (categories == null) { // force refreshing refreshDashboardTiles(getLogTag()); } else if (categories.contains(categoryKey)) { Log.i(TAG, "refresh tiles for " + categoryKey); refreshDashboardTiles(getLogTag()); } } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { Loading Loading
src/com/android/settings/core/SettingsBaseActivity.java +79 −13 Original line number Diff line number Diff line Loading @@ -41,11 +41,14 @@ import androidx.fragment.app.FragmentActivity; import com.android.settings.R; import com.android.settings.SubSettings; import com.android.settings.dashboard.CategoryManager; import com.android.settingslib.drawer.Tile; import com.google.android.setupcompat.util.WizardManagerHelper; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; public class SettingsBaseActivity extends FragmentActivity { Loading @@ -59,6 +62,7 @@ public class SettingsBaseActivity extends FragmentActivity { private final PackageReceiver mPackageReceiver = new PackageReceiver(); private final List<CategoryListener> mCategoryListeners = new ArrayList<>(); private int mCategoriesUpdateTaskCount; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { Loading Loading @@ -147,10 +151,10 @@ public class SettingsBaseActivity extends FragmentActivity { ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params); } private void onCategoriesChanged() { private void onCategoriesChanged(Set<String> categories) { final int N = mCategoryListeners.size(); for (int i = 0; i < N; i++) { mCategoryListeners.get(i).onCategoriesChanged(); mCategoryListeners.get(i).onCategoriesChanged(categories); } } Loading Loading @@ -194,38 +198,100 @@ public class SettingsBaseActivity extends FragmentActivity { * Updates dashboard categories. Only necessary to call this after setTileEnabled */ public void updateCategories() { new CategoriesUpdateTask().execute(); updateCategories(false /* fromBroadcast */); } private void updateCategories(boolean fromBroadcast) { // Only allow at most 2 tasks existing at the same time since when the first one is // executing, there may be new data from the second update request. // Ignore the third update request because the second task is still waiting for the first // task to complete in a serial thread, which will get the latest data. if (mCategoriesUpdateTaskCount < 2) { new CategoriesUpdateTask().execute(fromBroadcast); } } public interface CategoryListener { void onCategoriesChanged(); /** * @param categories the changed categories that have to be refreshed, or null to force * refreshing all. */ void onCategoriesChanged(@Nullable Set<String> categories); } private class CategoriesUpdateTask extends AsyncTask<Void, Void, Void> { private class CategoriesUpdateTask extends AsyncTask<Boolean, Void, Set<String>> { private final Context mContext; private final CategoryManager mCategoryManager; private Map<ComponentName, Tile> mPreviousTileMap; public CategoriesUpdateTask() { mCategoryManager = CategoryManager.get(SettingsBaseActivity.this); mCategoriesUpdateTaskCount++; mContext = SettingsBaseActivity.this; mCategoryManager = CategoryManager.get(mContext); } @Override protected Void doInBackground(Void... params) { mCategoryManager.reloadAllCategories(SettingsBaseActivity.this); return null; protected Set<String> doInBackground(Boolean... params) { mPreviousTileMap = mCategoryManager.getTileByComponentMap(); mCategoryManager.reloadAllCategories(mContext); mCategoryManager.updateCategoryFromDenylist(sTileDenylist); return getChangedCategories(params[0]); } @Override protected void onPostExecute(Void result) { mCategoryManager.updateCategoryFromDenylist(sTileDenylist); onCategoriesChanged(); protected void onPostExecute(Set<String> categories) { if (categories == null || !categories.isEmpty()) { onCategoriesChanged(categories); } mCategoriesUpdateTaskCount--; } // Return the changed categories that have to be refreshed, or null to force refreshing all. private Set<String> getChangedCategories(boolean fromBroadcast) { if (!fromBroadcast) { // Always refresh for non-broadcast case. return null; } final Set<String> changedCategories = new ArraySet<>(); final Map<ComponentName, Tile> currentTileMap = mCategoryManager.getTileByComponentMap(); currentTileMap.forEach((component, currentTile) -> { final Tile previousTile = mPreviousTileMap.get(component); // Check if the tile is newly added. if (previousTile == null) { Log.i(TAG, "Tile added: " + component.flattenToShortString()); changedCategories.add(currentTile.getCategory()); return; } // Check if the title or summary has changed. if (!TextUtils.equals(currentTile.getTitle(mContext), previousTile.getTitle(mContext)) || !TextUtils.equals(currentTile.getSummary(mContext), previousTile.getSummary(mContext))) { Log.i(TAG, "Tile changed: " + component.flattenToShortString()); changedCategories.add(currentTile.getCategory()); } }); // Check if any previous tile is removed. final Set<ComponentName> removal = new ArraySet(mPreviousTileMap.keySet()); removal.removeAll(currentTileMap.keySet()); removal.forEach(component -> { Log.i(TAG, "Tile removed: " + component.flattenToShortString()); changedCategories.add(mPreviousTileMap.get(component).getCategory()); }); return changedCategories; } } private class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { updateCategories(); updateCategories(true /* fromBroadcast */); } } }
src/com/android/settings/dashboard/CategoryManager.java +31 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import java.util.Set; public class CategoryManager { private static final String TAG = "CategoryManager"; private static final boolean DEBUG = false; private static CategoryManager sInstance; private final InterestingConfigChanges mInterestingConfigChanges; Loading Loading @@ -92,6 +93,7 @@ public class CategoryManager { public synchronized void updateCategoryFromDenylist(Set<ComponentName> tileDenylist) { if (mCategories == null) { Log.w(TAG, "Category is null, skipping denylist update"); return; } for (int i = 0; i < mCategories.size(); i++) { DashboardCategory category = mCategories.get(i); Loading @@ -104,6 +106,31 @@ public class CategoryManager { } } /** Return the current tile map */ public synchronized Map<ComponentName, Tile> getTileByComponentMap() { final Map<ComponentName, Tile> result = new ArrayMap<>(); if (mCategories == null) { Log.w(TAG, "Category is null, no tiles"); return result; } mCategories.forEach(category -> { for (int i = 0; i < category.getTilesCount(); i++) { final Tile tile = category.getTile(i); result.put(tile.getIntent().getComponent(), tile); } }); return result; } private void logTiles(Context context) { if (DEBUG) { getTileByComponentMap().forEach((component, tile) -> { Log.d(TAG, "Tile: " + tile.getCategory().replace("com.android.settings.", "") + ": " + tile.getTitle(context) + ", " + component.flattenToShortString()); }); } } private synchronized void tryInitCategories(Context context) { // Keep cached tiles by default. The cache is only invalidated when InterestingConfigChange // happens. Loading @@ -112,6 +139,7 @@ public class CategoryManager { private synchronized void tryInitCategories(Context context, boolean forceClearCache) { if (mCategories == null) { final boolean firstLoading = mCategoryByKeyMap.isEmpty(); if (forceClearCache) { mTileByComponentCache.clear(); } Loading @@ -123,6 +151,9 @@ public class CategoryManager { backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); sortCategories(context, mCategoryByKeyMap); filterDuplicateTiles(mCategoryByKeyMap); if (firstLoading) { logTiles(context); } } } Loading
src/com/android/settings/dashboard/DashboardFragment.java +14 −5 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.ExecutionException; /** Loading Loading @@ -160,14 +161,22 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment } @Override public void onCategoriesChanged() { final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(getCategoryKey()); if (category == null) { public void onCategoriesChanged(Set<String> categories) { final String categoryKey = getCategoryKey(); final DashboardCategory dashboardCategory = mDashboardFeatureProvider.getTilesForCategory(categoryKey); if (dashboardCategory == null) { return; } if (categories == null) { // force refreshing refreshDashboardTiles(getLogTag()); } else if (categories.contains(categoryKey)) { Log.i(TAG, "refresh tiles for " + categoryKey); refreshDashboardTiles(getLogTag()); } } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { Loading