1 /* 2 * Copyright (C) 2018 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 */ 16 17 package com.android.settings.homepage; 18 19 import static com.android.settings.search.actionbar.SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR; 20 import static com.android.settingslib.search.SearchIndexable.MOBILE; 21 22 import android.app.ActivityManager; 23 import android.app.settings.SettingsEnums; 24 import android.content.Context; 25 import android.content.res.Configuration; 26 import android.graphics.drawable.Drawable; 27 import android.os.Bundle; 28 import android.text.TextUtils; 29 import android.util.Log; 30 31 import androidx.fragment.app.Fragment; 32 import androidx.preference.Preference; 33 import androidx.preference.PreferenceFragmentCompat; 34 import androidx.preference.PreferenceScreen; 35 import androidx.recyclerview.widget.RecyclerView; 36 37 import com.android.settings.R; 38 import com.android.settings.Utils; 39 import com.android.settings.activityembedding.ActivityEmbeddingRulesController; 40 import com.android.settings.activityembedding.ActivityEmbeddingUtils; 41 import com.android.settings.core.SubSettingLauncher; 42 import com.android.settings.dashboard.DashboardFragment; 43 import com.android.settings.search.BaseSearchIndexProvider; 44 import com.android.settings.support.SupportPreferenceController; 45 import com.android.settings.widget.HomepagePreference; 46 import com.android.settingslib.core.instrumentation.Instrumentable; 47 import com.android.settingslib.drawer.Tile; 48 import com.android.settingslib.search.SearchIndexable; 49 50 @SearchIndexable(forTarget = MOBILE) 51 public class TopLevelSettings extends DashboardFragment implements 52 PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { 53 54 private static final String TAG = "TopLevelSettings"; 55 private static final String SAVED_HIGHLIGHT_MIXIN = "highlight_mixin"; 56 private static final String PREF_KEY_SUPPORT = "top_level_support"; 57 58 private boolean mIsEmbeddingActivityEnabled; 59 private TopLevelHighlightMixin mHighlightMixin; 60 private boolean mFirstStarted = true; 61 TopLevelSettings()62 public TopLevelSettings() { 63 final Bundle args = new Bundle(); 64 // Disable the search icon because this page uses a full search view in actionbar. 65 args.putBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, false); 66 setArguments(args); 67 } 68 69 @Override getPreferenceScreenResId()70 protected int getPreferenceScreenResId() { 71 return R.xml.top_level_settings; 72 } 73 74 @Override getLogTag()75 protected String getLogTag() { 76 return TAG; 77 } 78 79 @Override getMetricsCategory()80 public int getMetricsCategory() { 81 return SettingsEnums.DASHBOARD_SUMMARY; 82 } 83 84 @Override onAttach(Context context)85 public void onAttach(Context context) { 86 super.onAttach(context); 87 HighlightableMenu.fromXml(context, getPreferenceScreenResId()); 88 use(SupportPreferenceController.class).setActivity(getActivity()); 89 } 90 91 @Override getHelpResource()92 public int getHelpResource() { 93 // Disable the help icon because this page uses a full search view in actionbar. 94 return 0; 95 } 96 97 @Override getCallbackFragment()98 public Fragment getCallbackFragment() { 99 return this; 100 } 101 102 @Override onPreferenceTreeClick(Preference preference)103 public boolean onPreferenceTreeClick(Preference preference) { 104 // Register SplitPairRule for SubSettings. 105 ActivityEmbeddingRulesController.registerSubSettingsPairRule(getContext(), 106 true /* clearTop */); 107 108 setHighlightPreferenceKey(preference.getKey()); 109 return super.onPreferenceTreeClick(preference); 110 } 111 112 @Override onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref)113 public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) { 114 new SubSettingLauncher(getActivity()) 115 .setDestination(pref.getFragment()) 116 .setArguments(pref.getExtras()) 117 .setSourceMetricsCategory(caller instanceof Instrumentable 118 ? ((Instrumentable) caller).getMetricsCategory() 119 : Instrumentable.METRICS_CATEGORY_UNKNOWN) 120 .setTitleRes(-1) 121 .launch(); 122 return true; 123 } 124 125 @Override onCreate(Bundle icicle)126 public void onCreate(Bundle icicle) { 127 super.onCreate(icicle); 128 mIsEmbeddingActivityEnabled = 129 ActivityEmbeddingUtils.isEmbeddingActivityEnabled(getContext()); 130 if (!mIsEmbeddingActivityEnabled) { 131 return; 132 } 133 134 if (icicle != null) { 135 mHighlightMixin = icicle.getParcelable(SAVED_HIGHLIGHT_MIXIN); 136 } 137 if (mHighlightMixin == null) { 138 mHighlightMixin = new TopLevelHighlightMixin(); 139 } 140 } 141 142 @Override onStart()143 public void onStart() { 144 if (mFirstStarted) { 145 mFirstStarted = false; 146 } else if (mIsEmbeddingActivityEnabled && isOnlyOneActivityInTask() 147 && !ActivityEmbeddingUtils.isTwoPaneResolution(getActivity())) { 148 // Set default highlight menu key for 1-pane homepage since it will show the placeholder 149 // page once changing back to 2-pane. 150 Log.i(TAG, "Set default menu key"); 151 setHighlightMenuKey(getString(SettingsHomepageActivity.DEFAULT_HIGHLIGHT_MENU_KEY), 152 /* scrollNeeded= */ false); 153 } 154 super.onStart(); 155 } 156 isOnlyOneActivityInTask()157 private boolean isOnlyOneActivityInTask() { 158 final ActivityManager.RunningTaskInfo taskInfo = getSystemService(ActivityManager.class) 159 .getRunningTasks(1).get(0); 160 return taskInfo.numActivities == 1; 161 } 162 163 @Override onSaveInstanceState(Bundle outState)164 public void onSaveInstanceState(Bundle outState) { 165 super.onSaveInstanceState(outState); 166 if (mHighlightMixin != null) { 167 outState.putParcelable(SAVED_HIGHLIGHT_MIXIN, mHighlightMixin); 168 } 169 } 170 171 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)172 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 173 super.onCreatePreferences(savedInstanceState, rootKey); 174 final PreferenceScreen screen = getPreferenceScreen(); 175 if (screen == null) { 176 return; 177 } 178 // Tint the homepage icons 179 final int tintColor = Utils.getHomepageIconColor(getContext()); 180 final int count = screen.getPreferenceCount(); 181 for (int i = 0; i < count; i++) { 182 final Preference preference = screen.getPreference(i); 183 if (preference == null) { 184 break; 185 } 186 final Drawable icon = preference.getIcon(); 187 if (icon != null) { 188 icon.setTint(tintColor); 189 } 190 } 191 } 192 193 @Override onConfigurationChanged(Configuration newConfig)194 public void onConfigurationChanged(Configuration newConfig) { 195 super.onConfigurationChanged(newConfig); 196 highlightPreferenceIfNeeded(); 197 } 198 199 @Override highlightPreferenceIfNeeded()200 public void highlightPreferenceIfNeeded() { 201 if (mHighlightMixin != null) { 202 mHighlightMixin.highlightPreferenceIfNeeded(getActivity()); 203 } 204 } 205 206 /** Returns a {@link TopLevelHighlightMixin} that performs highlighting */ getHighlightMixin()207 public TopLevelHighlightMixin getHighlightMixin() { 208 return mHighlightMixin; 209 } 210 211 /** Highlight a preference with specified preference key */ setHighlightPreferenceKey(String prefKey)212 public void setHighlightPreferenceKey(String prefKey) { 213 // Skip Tips & support since it's full screen 214 if (mHighlightMixin != null && !TextUtils.equals(prefKey, PREF_KEY_SUPPORT)) { 215 mHighlightMixin.setHighlightPreferenceKey(prefKey); 216 } 217 } 218 219 /** Show/hide the highlight on the menu entry for the search page presence */ setMenuHighlightShowed(boolean show)220 public void setMenuHighlightShowed(boolean show) { 221 if (mHighlightMixin != null) { 222 mHighlightMixin.setMenuHighlightShowed(show); 223 } 224 } 225 226 /** Highlight and scroll to a preference with specified menu key */ setHighlightMenuKey(String menuKey, boolean scrollNeeded)227 public void setHighlightMenuKey(String menuKey, boolean scrollNeeded) { 228 if (mHighlightMixin != null) { 229 mHighlightMixin.setHighlightMenuKey(menuKey, scrollNeeded); 230 } 231 } 232 233 @Override shouldForceRoundedIcon()234 protected boolean shouldForceRoundedIcon() { 235 return getContext().getResources() 236 .getBoolean(R.bool.config_force_rounded_icon_TopLevelSettings); 237 } 238 239 @Override onCreateAdapter(PreferenceScreen preferenceScreen)240 protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { 241 if (!mIsEmbeddingActivityEnabled || !(getActivity() instanceof SettingsHomepageActivity)) { 242 return super.onCreateAdapter(preferenceScreen); 243 } 244 return mHighlightMixin.onCreateAdapter(this, preferenceScreen); 245 } 246 247 @Override createPreference(Tile tile)248 protected Preference createPreference(Tile tile) { 249 return new HomepagePreference(getPrefContext()); 250 } 251 reloadHighlightMenuKey()252 void reloadHighlightMenuKey() { 253 if (mHighlightMixin != null) { 254 mHighlightMixin.reloadHighlightMenuKey(getArguments()); 255 } 256 } 257 258 public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 259 new BaseSearchIndexProvider(R.xml.top_level_settings) { 260 261 @Override 262 protected boolean isPageSearchEnabled(Context context) { 263 // Never searchable, all entries in this page are already indexed elsewhere. 264 return false; 265 } 266 }; 267 } 268