blob: 3575b7293dbed5494007cf66e43048dcfdd22c47 [file] [log] [blame]
Fan Zhangbb6d2602016-10-04 13:21:06 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.settings.dashboard;
17
18import android.app.Activity;
Fan Zhangff47b302018-11-09 14:52:42 -080019import android.app.settings.SettingsEnums;
Fan Zhangbb6d2602016-10-04 13:21:06 -070020import android.content.Context;
Fan Zhang36924652016-10-07 08:38:48 -070021import android.os.Bundle;
Fan Zhangbb6d2602016-10-04 13:21:06 -070022import android.text.TextUtils;
23import android.util.ArrayMap;
Fan Zhang7f1a4b52016-10-12 12:35:52 -070024import android.util.ArraySet;
Fan Zhangbb6d2602016-10-04 13:21:06 -070025import android.util.Log;
26
Yanting Yang4e56cb22019-04-18 21:37:31 +080027import androidx.annotation.CallSuper;
Fan Zhang1c61a582018-07-26 11:26:11 -070028import androidx.annotation.VisibleForTesting;
29import androidx.preference.Preference;
Doris Ling8741c042018-08-27 14:11:55 -070030import androidx.preference.PreferenceGroup;
Fan Zhang1c61a582018-07-26 11:26:11 -070031import androidx.preference.PreferenceManager;
32import androidx.preference.PreferenceScreen;
33
Yanting Yang4e56cb22019-04-18 21:37:31 +080034import com.android.settings.R;
Fan Zhangbb6d2602016-10-04 13:21:06 -070035import com.android.settings.SettingsPreferenceFragment;
Fan Zhang917f1012018-02-21 15:22:25 -080036import com.android.settings.core.BasePreferenceController;
37import com.android.settings.core.PreferenceControllerListHelper;
tmfangd97fba52018-06-14 14:48:35 +080038import com.android.settings.core.SettingsBaseActivity;
Fan Zhangbb6d2602016-10-04 13:21:06 -070039import com.android.settings.overlay.FeatureFactory;
Tony Mantler1d583e12017-06-13 13:09:25 -070040import com.android.settingslib.core.AbstractPreferenceController;
Fan Zhang917f1012018-02-21 15:22:25 -080041import com.android.settingslib.core.lifecycle.Lifecycle;
42import com.android.settingslib.core.lifecycle.LifecycleObserver;
Fan Zhangbb6d2602016-10-04 13:21:06 -070043import com.android.settingslib.drawer.DashboardCategory;
Fan Zhangbb6d2602016-10-04 13:21:06 -070044import com.android.settingslib.drawer.Tile;
Raff Tsai6db277e2019-10-02 16:43:23 +080045import com.android.settingslib.search.Indexable;
Fan Zhangbb6d2602016-10-04 13:21:06 -070046
Fan Zhanga1a84e62016-10-19 14:15:34 -070047import java.util.ArrayList;
Yanting Yang4e56cb22019-04-18 21:37:31 +080048import java.util.Arrays;
Fan Zhangbb6d2602016-10-04 13:21:06 -070049import java.util.Collection;
50import java.util.List;
51import java.util.Map;
Fan Zhang7f1a4b52016-10-12 12:35:52 -070052import java.util.Set;
Fan Zhangbb6d2602016-10-04 13:21:06 -070053
54/**
55 * Base fragment for dashboard style UI containing a list of static and dynamic setting items.
56 */
57public abstract class DashboardFragment extends SettingsPreferenceFragment
tmfangd97fba52018-06-14 14:48:35 +080058 implements SettingsBaseActivity.CategoryListener, Indexable,
Raff Tsai6db277e2019-10-02 16:43:23 +080059 PreferenceGroup.OnExpandButtonClickListener,
jackqdyulei22904a02018-12-27 14:40:09 -080060 BasePreferenceController.UiBlockListener {
Fan Zhangdb1112a2016-10-18 12:58:31 -070061 private static final String TAG = "DashboardFragment";
Fan Zhangbb6d2602016-10-04 13:21:06 -070062
Ben Lin92751772017-12-21 17:32:34 -080063 private final Map<Class, List<AbstractPreferenceController>> mPreferenceControllers =
Fan Zhangbb6d2602016-10-04 13:21:06 -070064 new ArrayMap<>();
Fan Zhang7f1a4b52016-10-12 12:35:52 -070065 private final Set<String> mDashboardTilePrefKeys = new ArraySet<>();
hughchend49de612019-09-24 10:30:49 +080066 private final List<AbstractPreferenceController> mControllers = new ArrayList<>();
Fan Zhangbb6d2602016-10-04 13:21:06 -070067
Fan Zhangb297abc2018-02-21 09:37:10 -080068 private DashboardFeatureProvider mDashboardFeatureProvider;
Fan Zhang9dc9c612016-11-11 13:23:21 -080069 private DashboardTilePlaceholderPreferenceController mPlaceholderPreferenceController;
Fan Zhang36924652016-10-07 08:38:48 -070070 private boolean mListeningToCategoryChange;
Yanting Yang4e56cb22019-04-18 21:37:31 +080071 private List<String> mSuppressInjectedTileKeys;
jackqdyuleia5f1b5c2019-01-14 10:55:39 -080072 @VisibleForTesting
73 UiBlockerController mBlockerController;
Fan Zhangbb6d2602016-10-04 13:21:06 -070074
75 @Override
76 public void onAttach(Context context) {
77 super.onAttach(context);
Yanting Yang4e56cb22019-04-18 21:37:31 +080078 mSuppressInjectedTileKeys = Arrays.asList(context.getResources().getStringArray(
79 R.array.config_suppress_injected_tile_keys));
Fan Zhang917f1012018-02-21 15:22:25 -080080 mDashboardFeatureProvider = FeatureFactory.getFactory(context).
81 getDashboardFeatureProvider(context);
Fan Zhang917f1012018-02-21 15:22:25 -080082 // Load preference controllers from code
83 final List<AbstractPreferenceController> controllersFromCode =
Fan Zhangf7843ad2018-02-22 13:51:41 -080084 createPreferenceControllers(context);
Fan Zhang917f1012018-02-21 15:22:25 -080085 // Load preference controllers from xml definition
86 final List<BasePreferenceController> controllersFromXml = PreferenceControllerListHelper
87 .getPreferenceControllersFromXml(context, getPreferenceScreenResId());
88 // Filter xml-based controllers in case a similar controller is created from code already.
89 final List<BasePreferenceController> uniqueControllerFromXml =
90 PreferenceControllerListHelper.filterControllers(
91 controllersFromXml, controllersFromCode);
Fan Zhang66b573a2016-10-06 16:33:13 -070092
Fan Zhang917f1012018-02-21 15:22:25 -080093 // Add unique controllers to list.
94 if (controllersFromCode != null) {
hughchend49de612019-09-24 10:30:49 +080095 mControllers.addAll(controllersFromCode);
Fan Zhang66b573a2016-10-06 16:33:13 -070096 }
hughchend49de612019-09-24 10:30:49 +080097 mControllers.addAll(uniqueControllerFromXml);
Fan Zhang917f1012018-02-21 15:22:25 -080098
99 // And wire up with lifecycle.
tmfang27c84de2018-06-28 11:39:05 +0800100 final Lifecycle lifecycle = getSettingsLifecycle();
Jason Chiu1a1f9312019-10-01 17:35:00 +0800101 uniqueControllerFromXml.forEach(controller -> {
102 if (controller instanceof LifecycleObserver) {
103 lifecycle.addObserver((LifecycleObserver) controller);
104 }
105 });
Fan Zhang917f1012018-02-21 15:22:25 -0800106
Fan Zhang9dc9c612016-11-11 13:23:21 -0800107 mPlaceholderPreferenceController =
108 new DashboardTilePlaceholderPreferenceController(context);
hughchend49de612019-09-24 10:30:49 +0800109 mControllers.add(mPlaceholderPreferenceController);
110 for (AbstractPreferenceController controller : mControllers) {
Fan Zhang66b573a2016-10-06 16:33:13 -0700111 addPreferenceController(controller);
112 }
jackqdyulei22904a02018-12-27 14:40:09 -0800113 }
114
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800115 @VisibleForTesting
116 void checkUiBlocker(List<AbstractPreferenceController> controllers) {
jackqdyulei22904a02018-12-27 14:40:09 -0800117 final List<String> keys = new ArrayList<>();
Jason Chiu1a1f9312019-10-01 17:35:00 +0800118 controllers.forEach(controller -> {
119 if (controller instanceof BasePreferenceController.UiBlocker
120 && controller.isAvailable()) {
121 ((BasePreferenceController) controller).setUiBlockListener(this);
122 keys.add(controller.getPreferenceKey());
123 }
124 });
jackqdyulei22904a02018-12-27 14:40:09 -0800125
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800126 if (!keys.isEmpty()) {
127 mBlockerController = new UiBlockerController(keys);
Raff Tsai6db277e2019-10-02 16:43:23 +0800128 mBlockerController.start(() -> updatePreferenceVisibility(mPreferenceControllers));
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800129 }
Fan Zhangbb6d2602016-10-04 13:21:06 -0700130 }
131
132 @Override
Fan Zhanga1a84e62016-10-19 14:15:34 -0700133 public void onCreate(Bundle icicle) {
134 super.onCreate(icicle);
135 // Set ComparisonCallback so we get better animation when list changes.
136 getPreferenceManager().setPreferenceComparisonCallback(
137 new PreferenceManager.SimplePreferenceComparisonCallback());
jeffreyhuangbf234af2017-11-14 15:09:12 -0800138 if (icicle != null) {
139 // Upon rotation configuration change we need to update preference states before any
140 // editing dialog is recreated (that would happen before onResume is called).
141 updatePreferenceStates();
142 }
Fan Zhanga1a84e62016-10-19 14:15:34 -0700143 }
144
145 @Override
Fan Zhang36924652016-10-07 08:38:48 -0700146 public void onCategoriesChanged() {
Fan Zhangfabbfb42016-10-07 12:41:43 -0700147 final DashboardCategory category =
148 mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());
Fan Zhang36924652016-10-07 08:38:48 -0700149 if (category == null) {
150 return;
151 }
Fan Zhang7f1a4b52016-10-12 12:35:52 -0700152 refreshDashboardTiles(getLogTag());
Fan Zhang36924652016-10-07 08:38:48 -0700153 }
154
155 @Override
156 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
hughchend49de612019-09-24 10:30:49 +0800157 checkUiBlocker(mControllers);
Fan Zhang36924652016-10-07 08:38:48 -0700158 refreshAllPreferences(getLogTag());
159 }
160
161 @Override
Fan Zhangbb6d2602016-10-04 13:21:06 -0700162 public void onStart() {
163 super.onStart();
Fan Zhangfabbfb42016-10-07 12:41:43 -0700164 final DashboardCategory category =
165 mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());
Fan Zhang36924652016-10-07 08:38:48 -0700166 if (category == null) {
167 return;
168 }
Fan Zhangbb6d2602016-10-04 13:21:06 -0700169 final Activity activity = getActivity();
tmfangd97fba52018-06-14 14:48:35 +0800170 if (activity instanceof SettingsBaseActivity) {
Fan Zhang36924652016-10-07 08:38:48 -0700171 mListeningToCategoryChange = true;
tmfangd97fba52018-06-14 14:48:35 +0800172 ((SettingsBaseActivity) activity).addCategoryListener(this);
Fan Zhangbb6d2602016-10-04 13:21:06 -0700173 }
174 }
175
176 @Override
Fan Zhang66b573a2016-10-06 16:33:13 -0700177 public void onResume() {
178 super.onResume();
179 updatePreferenceStates();
180 }
181
182 @Override
Fan Zhangbb6d2602016-10-04 13:21:06 -0700183 public boolean onPreferenceTreeClick(Preference preference) {
Ben Lin92751772017-12-21 17:32:34 -0800184 Collection<List<AbstractPreferenceController>> controllers =
185 mPreferenceControllers.values();
Fan Zhangee459432017-02-23 10:59:47 -0800186 // If preference contains intent, log it before handling.
187 mMetricsFeatureProvider.logDashboardStartIntent(
188 getContext(), preference.getIntent(), getMetricsCategory());
Fan Zhangbb6d2602016-10-04 13:21:06 -0700189 // Give all controllers a chance to handle click.
Ben Lin92751772017-12-21 17:32:34 -0800190 for (List<AbstractPreferenceController> controllerList : controllers) {
191 for (AbstractPreferenceController controller : controllerList) {
192 if (controller.handlePreferenceTreeClick(preference)) {
193 return true;
194 }
Fan Zhangbb6d2602016-10-04 13:21:06 -0700195 }
196 }
197 return super.onPreferenceTreeClick(preference);
198 }
199
200 @Override
201 public void onStop() {
202 super.onStop();
Fan Zhang36924652016-10-07 08:38:48 -0700203 if (mListeningToCategoryChange) {
204 final Activity activity = getActivity();
tmfangd97fba52018-06-14 14:48:35 +0800205 if (activity instanceof SettingsBaseActivity) {
206 ((SettingsBaseActivity) activity).remCategoryListener(this);
Fan Zhang36924652016-10-07 08:38:48 -0700207 }
208 mListeningToCategoryChange = false;
Fan Zhangbb6d2602016-10-04 13:21:06 -0700209 }
210 }
211
Fan Zhang9679dba2017-10-31 14:27:18 -0700212 @Override
213 protected abstract int getPreferenceScreenResId();
214
Doris Ling8741c042018-08-27 14:11:55 -0700215 @Override
216 public void onExpandButtonClick() {
Fan Zhangff47b302018-11-09 14:52:42 -0800217 mMetricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
Fan Zhang31b21002019-01-16 13:49:47 -0800218 SettingsEnums.ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND,
Fan Zhangff47b302018-11-09 14:52:42 -0800219 getMetricsCategory(), null, 0);
Doris Ling8741c042018-08-27 14:11:55 -0700220 }
221
Fan Zhang7d5a9ee2018-08-09 17:32:37 -0700222 protected boolean shouldForceRoundedIcon() {
223 return false;
224 }
225
Fan Zhangf7843ad2018-02-22 13:51:41 -0800226 protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
Ben Lin92751772017-12-21 17:32:34 -0800227 List<AbstractPreferenceController> controllerList = mPreferenceControllers.get(clazz);
228 if (controllerList != null) {
229 if (controllerList.size() > 1) {
230 Log.w(TAG, "Multiple controllers of Class " + clazz.getSimpleName()
231 + " found, returning first one.");
232 }
233 return (T) controllerList.get(0);
234 }
235
236 return null;
Fan Zhangbb6d2602016-10-04 13:21:06 -0700237 }
238
Tony Mantler1d583e12017-06-13 13:09:25 -0700239 protected void addPreferenceController(AbstractPreferenceController controller) {
Ben Lin92751772017-12-21 17:32:34 -0800240 if (mPreferenceControllers.get(controller.getClass()) == null) {
241 mPreferenceControllers.put(controller.getClass(), new ArrayList<>());
242 }
243 mPreferenceControllers.get(controller.getClass()).add(controller);
Fan Zhangbb6d2602016-10-04 13:21:06 -0700244 }
245
Fan Zhang36924652016-10-07 08:38:48 -0700246 /**
Fan Zhangfabbfb42016-10-07 12:41:43 -0700247 * Returns the CategoryKey for loading {@link DashboardCategory} for this fragment.
Fan Zhang36924652016-10-07 08:38:48 -0700248 */
Fan Zhang26a1def2017-07-26 10:58:32 -0700249 @VisibleForTesting
Fan Zhang7e6df832017-01-24 14:02:17 -0800250 public String getCategoryKey() {
251 return DashboardFragmentRegistry.PARENT_TO_CATEGORY_KEY_MAP.get(getClass().getName());
252 }
Fan Zhang36924652016-10-07 08:38:48 -0700253
254 /**
Fan Zhang66b573a2016-10-06 16:33:13 -0700255 * Get the tag string for logging.
256 */
257 protected abstract String getLogTag();
258
259 /**
Tony Mantler1d583e12017-06-13 13:09:25 -0700260 * Get a list of {@link AbstractPreferenceController} for this fragment.
Fan Zhang66b573a2016-10-06 16:33:13 -0700261 */
Fan Zhangf7843ad2018-02-22 13:51:41 -0800262 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
Fan Zhang917f1012018-02-21 15:22:25 -0800263 return null;
264 }
Fan Zhang66b573a2016-10-06 16:33:13 -0700265
266 /**
Doris Ling20d4b042016-11-22 16:37:06 -0800267 * Returns true if this tile should be displayed
268 */
Yanting Yang4e56cb22019-04-18 21:37:31 +0800269 @CallSuper
Doris Ling20d4b042016-11-22 16:37:06 -0800270 protected boolean displayTile(Tile tile) {
Yanting Yang4e56cb22019-04-18 21:37:31 +0800271 if (mSuppressInjectedTileKeys != null && tile.hasKey()) {
272 // For suppressing injected tiles for OEMs.
273 return !mSuppressInjectedTileKeys.contains(tile.getKey(getContext()));
274 }
Doris Ling20d4b042016-11-22 16:37:06 -0800275 return true;
276 }
277
278 /**
Fan Zhang36924652016-10-07 08:38:48 -0700279 * Displays resource based tiles.
280 */
Fan Zhang66b573a2016-10-06 16:33:13 -0700281 private void displayResourceTiles() {
282 final int resId = getPreferenceScreenResId();
283 if (resId <= 0) {
284 return;
285 }
286 addPreferencesFromResource(resId);
287 final PreferenceScreen screen = getPreferenceScreen();
Doris Ling8741c042018-08-27 14:11:55 -0700288 screen.setOnExpandButtonClickListener(this);
Ben Lin92751772017-12-21 17:32:34 -0800289 mPreferenceControllers.values().stream().flatMap(Collection::stream).forEach(
290 controller -> controller.displayPreference(screen));
Fan Zhang66b573a2016-10-06 16:33:13 -0700291 }
Fan Zhang36924652016-10-07 08:38:48 -0700292
293 /**
Fan Zhang8b5bca52016-10-19 12:00:32 -0700294 * Update state of each preference managed by PreferenceController.
Fan Zhang36924652016-10-07 08:38:48 -0700295 */
Fan Zhangbeddff82016-11-18 11:10:05 -0800296 protected void updatePreferenceStates() {
Fan Zhang8b5bca52016-10-19 12:00:32 -0700297 final PreferenceScreen screen = getPreferenceScreen();
Ben Lin92751772017-12-21 17:32:34 -0800298 Collection<List<AbstractPreferenceController>> controllerLists =
299 mPreferenceControllers.values();
300 for (List<AbstractPreferenceController> controllerList : controllerLists) {
301 for (AbstractPreferenceController controller : controllerList) {
302 if (!controller.isAvailable()) {
303 continue;
304 }
Jason Chiua42a93b2018-12-18 18:27:50 +0800305
Ben Lin92751772017-12-21 17:32:34 -0800306 final String key = controller.getPreferenceKey();
Jason Chiua42a93b2018-12-18 18:27:50 +0800307 if (TextUtils.isEmpty(key)) {
308 Log.d(TAG, String.format("Preference key is %s in Controller %s",
309 key, controller.getClass().getSimpleName()));
310 continue;
311 }
Fan Zhang8b5bca52016-10-19 12:00:32 -0700312
Ben Lin92751772017-12-21 17:32:34 -0800313 final Preference preference = screen.findPreference(key);
314 if (preference == null) {
315 Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
316 key, controller.getClass().getSimpleName()));
317 continue;
318 }
319 controller.updateState(preference);
Fan Zhang8b5bca52016-10-19 12:00:32 -0700320 }
Fan Zhang8b5bca52016-10-19 12:00:32 -0700321 }
322 }
323
Fan Zhang8b5bca52016-10-19 12:00:32 -0700324 /**
325 * Refresh all preference items, including both static prefs from xml, and dynamic items from
326 * DashboardCategory.
327 */
328 private void refreshAllPreferences(final String TAG) {
jackqdyulei22904a02018-12-27 14:40:09 -0800329 final PreferenceScreen screen = getPreferenceScreen();
Fan Zhang8b5bca52016-10-19 12:00:32 -0700330 // First remove old preferences.
jackqdyulei22904a02018-12-27 14:40:09 -0800331 if (screen != null) {
Fan Zhang8b5bca52016-10-19 12:00:32 -0700332 // Intentionally do not cache PreferenceScreen because it will be recreated later.
jackqdyulei22904a02018-12-27 14:40:09 -0800333 screen.removeAll();
Fan Zhang8b5bca52016-10-19 12:00:32 -0700334 }
335
336 // Add resource based tiles.
337 displayResourceTiles();
338
339 refreshDashboardTiles(TAG);
Fan Zhang293883b2018-10-26 14:53:12 -0700340
341 final Activity activity = getActivity();
342 if (activity != null) {
343 Log.d(TAG, "All preferences added, reporting fully drawn");
344 activity.reportFullyDrawn();
345 }
jackqdyulei22904a02018-12-27 14:40:09 -0800346
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800347 updatePreferenceVisibility(mPreferenceControllers);
jackqdyulei22904a02018-12-27 14:40:09 -0800348 }
349
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800350 @VisibleForTesting
351 void updatePreferenceVisibility(
352 Map<Class, List<AbstractPreferenceController>> preferenceControllers) {
jackqdyulei22904a02018-12-27 14:40:09 -0800353 final PreferenceScreen screen = getPreferenceScreen();
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800354 if (screen == null || preferenceControllers == null || mBlockerController == null) {
jackqdyulei22904a02018-12-27 14:40:09 -0800355 return;
356 }
357
358 final boolean visible = mBlockerController.isBlockerFinished();
359 for (List<AbstractPreferenceController> controllerList :
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800360 preferenceControllers.values()) {
jackqdyulei22904a02018-12-27 14:40:09 -0800361 for (AbstractPreferenceController controller : controllerList) {
362 final String key = controller.getPreferenceKey();
jackqdyuleia5f1b5c2019-01-14 10:55:39 -0800363 final Preference preference = findPreference(key);
jackqdyulei22904a02018-12-27 14:40:09 -0800364 if (preference != null) {
365 preference.setVisible(visible && controller.isAvailable());
366 }
367 }
368 }
Fan Zhang8b5bca52016-10-19 12:00:32 -0700369 }
370
371 /**
372 * Refresh preference items backed by DashboardCategory.
373 */
Fan Zhang701b65e2018-07-24 12:49:30 -0700374 @VisibleForTesting
Fan Zhanga1a84e62016-10-19 14:15:34 -0700375 void refreshDashboardTiles(final String TAG) {
Fan Zhang8b5bca52016-10-19 12:00:32 -0700376 final PreferenceScreen screen = getPreferenceScreen();
Fan Zhanga1a84e62016-10-19 14:15:34 -0700377
Fan Zhangfabbfb42016-10-07 12:41:43 -0700378 final DashboardCategory category =
379 mDashboardFeatureProvider.getTilesForCategory(getCategoryKey());
Fan Zhang36924652016-10-07 08:38:48 -0700380 if (category == null) {
Fan Zhanga1a84e62016-10-19 14:15:34 -0700381 Log.d(TAG, "NO dashboard tiles for " + TAG);
Fan Zhang36924652016-10-07 08:38:48 -0700382 return;
383 }
Doris Lingbcb76352017-11-22 17:29:21 -0800384 final List<Tile> tiles = category.getTiles();
Fan Zhange6c60c22016-10-04 17:48:32 -0700385 if (tiles == null) {
Fan Zhang9a1928e2018-08-02 12:59:55 -0700386 Log.d(TAG, "tile list is empty, skipping category " + category.key);
Fan Zhange6c60c22016-10-04 17:48:32 -0700387 return;
388 }
Fan Zhanga1a84e62016-10-19 14:15:34 -0700389 // Create a list to track which tiles are to be removed.
390 final List<String> remove = new ArrayList<>(mDashboardTilePrefKeys);
391
Fan Zhangfabbfb42016-10-07 12:41:43 -0700392 // Install dashboard tiles.
Fan Zhang7d5a9ee2018-08-09 17:32:37 -0700393 final boolean forceRoundedIcons = shouldForceRoundedIcon();
Fan Zhangbb6d2602016-10-04 13:21:06 -0700394 for (Tile tile : tiles) {
395 final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
396 if (TextUtils.isEmpty(key)) {
397 Log.d(TAG, "tile does not contain a key, skipping " + tile);
398 continue;
399 }
Doris Ling20d4b042016-11-22 16:37:06 -0800400 if (!displayTile(tile)) {
401 continue;
402 }
Fan Zhanga1a84e62016-10-19 14:15:34 -0700403 if (mDashboardTilePrefKeys.contains(key)) {
404 // Have the key already, will rebind.
Doris Ling8b14a1a2017-08-17 14:45:12 -0700405 final Preference preference = screen.findPreference(key);
Fan Zhang7d5a9ee2018-08-09 17:32:37 -0700406 mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), forceRoundedIcons,
407 getMetricsCategory(), preference, tile, key,
408 mPlaceholderPreferenceController.getOrder());
Fan Zhanga1a84e62016-10-19 14:15:34 -0700409 } else {
410 // Don't have this key, add it.
Fan Zhang8b30f532016-10-31 14:40:15 -0700411 final Preference pref = new Preference(getPrefContext());
Fan Zhang7d5a9ee2018-08-09 17:32:37 -0700412 mDashboardFeatureProvider.bindPreferenceToTile(getActivity(), forceRoundedIcons,
413 getMetricsCategory(), pref, tile, key,
414 mPlaceholderPreferenceController.getOrder());
Doris Ling8b14a1a2017-08-17 14:45:12 -0700415 screen.addPreference(pref);
Fan Zhanga1a84e62016-10-19 14:15:34 -0700416 mDashboardTilePrefKeys.add(key);
Fan Zhangbb6d2602016-10-04 13:21:06 -0700417 }
Fan Zhanga1a84e62016-10-19 14:15:34 -0700418 remove.remove(key);
Fan Zhangbb6d2602016-10-04 13:21:06 -0700419 }
Fan Zhanga1a84e62016-10-19 14:15:34 -0700420 // Finally remove tiles that are gone.
421 for (String key : remove) {
422 mDashboardTilePrefKeys.remove(key);
Doris Ling8b14a1a2017-08-17 14:45:12 -0700423 final Preference preference = screen.findPreference(key);
424 if (preference != null) {
425 screen.removePreference(preference);
426 }
Fan Zhanga1a84e62016-10-19 14:15:34 -0700427 }
428 }
jackqdyulei22904a02018-12-27 14:40:09 -0800429
430 @Override
431 public void onBlockerWorkFinished(BasePreferenceController controller) {
432 mBlockerController.countDown(controller.getPreferenceKey());
433 }
Fan Zhangbb6d2602016-10-04 13:21:06 -0700434}