• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.tv.settings;
2 
3 import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected;
4 
5 import android.app.tvsettings.TvSettingsEnums;
6 import android.content.ActivityNotFoundException;
7 import android.content.ComponentName;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.service.settings.suggestions.Suggestion;
11 import android.util.Log;
12 
13 import androidx.annotation.VisibleForTesting;
14 import androidx.preference.Preference;
15 import androidx.preference.PreferenceCategory;
16 
17 import com.android.settingslib.core.AbstractPreferenceController;
18 import com.android.settingslib.suggestions.SuggestionControllerMixinCompat;
19 import com.android.settingslib.utils.IconCache;
20 import com.android.tv.settings.R;
21 import com.android.tv.settings.overlay.FlavorUtils;
22 import com.android.tv.settings.suggestions.SuggestionPreference;
23 import com.android.tv.settings.system.SecurityFragment;
24 import com.android.tv.settings.widget.SwitchWithSoundPreference;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 public class SuggestionQuickSettingPrefsContainer  {
30     @VisibleForTesting static final String KEY_QUICK_SETTINGS = "quick_settings";
31     private static final String TAG = "SuggestionQuickSettingPrefsContainer";
32     private static final String KEY_SUGGESTIONS_LIST = "suggestions";
33     @VisibleForTesting PreferenceCategory mSuggestionsList;
34     IconCache mIconCache;
35     private SuggestionControllerMixinCompat mSuggestionControllerMixin;
36     /** Controllers for the Quick Settings section. */
37     private List<AbstractPreferenceController> mPreferenceControllers;
38 
39     private HotwordSwitchController mHotwordSwitchController;
40     private TakeBugReportController mTakeBugReportController;
41     private PreferenceCategory mQuickSettingsList;
42     private SwitchWithSoundPreference mHotwordSwitch;
43     private Preference mTakeBugReportPreference;
44     private MainFragment mainFragment;
45 
SuggestionQuickSettingPrefsContainer(MainFragment mainFragment)46     SuggestionQuickSettingPrefsContainer(MainFragment mainFragment) {
47         this.mainFragment = mainFragment;
48     }
49 
onCreate()50     void onCreate() {
51         mIconCache = new IconCache(mainFragment.getContext());
52         if (!isRestricted()) {
53             ComponentName componentName = new ComponentName("com.android.settings.intelligence",
54                     "com.android.settings.intelligence.suggestions.SuggestionService");
55             mSuggestionControllerMixin =
56                     new SuggestionControllerMixinCompat(mainFragment.getContext(),
57                     mainFragment, mainFragment.getSettingsLifecycle(), componentName);
58         }
59     }
60 
onDestroy()61     void onDestroy() {
62         if (mHotwordSwitchController != null) {
63             mHotwordSwitchController.unregister();
64         }
65     }
66 
showOrHideQuickSettings()67     void showOrHideQuickSettings() {
68         if (shouldShowQuickSettings()) {
69             showQuickSettings();
70         } else {
71             hideQuickSettings();
72         }
73     }
74 
onCreatePreferences()75     void onCreatePreferences() {
76         if (mHotwordSwitchController != null) {
77             mHotwordSwitchController.init(mainFragment);
78         }
79     }
80 
onSuggestionReady(List<Suggestion> data)81     void onSuggestionReady(List<Suggestion> data) {
82         // Suggestion category is handled differently in basic mode
83         if (data == null || data.size() == 0
84                 || FlavorUtils.getFeatureFactory(mainFragment.getContext())
85                 .getBasicModeFeatureProvider()
86                 .isBasicMode(mainFragment.getContext())) {
87             if (mSuggestionsList != null) {
88                 mainFragment.getPreferenceScreen().removePreference(mSuggestionsList);
89                 mSuggestionsList = null;
90             }
91             return;
92         }
93 
94         if (mSuggestionsList == null) {
95             mSuggestionsList = new PreferenceCategory(
96                     mainFragment.getPreferenceManager().getContext());
97             mSuggestionsList.setKey(KEY_SUGGESTIONS_LIST);
98             mSuggestionsList.setTitle(R.string.header_category_suggestions);
99             mSuggestionsList.setOrder(0); // always at top
100             mainFragment.getPreferenceScreen().addPreference(mSuggestionsList);
101         }
102         updateSuggestionList(data);
103     }
104 
105     @VisibleForTesting
updateSuggestionList(List<Suggestion> suggestions)106     void updateSuggestionList(List<Suggestion> suggestions) {
107         // Remove suggestions that are not in the new list.
108         for (int i = 0; i < mSuggestionsList.getPreferenceCount(); i++) {
109             SuggestionPreference pref = (SuggestionPreference) mSuggestionsList.getPreference(i);
110             boolean isInNewSuggestionList = false;
111             for (Suggestion suggestion : suggestions) {
112                 if (pref.getId().equals(suggestion.getId())) {
113                     isInNewSuggestionList = true;
114                     break;
115                 }
116             }
117             if (!isInNewSuggestionList) {
118                 mSuggestionsList.removePreference(pref);
119             }
120         }
121 
122         // Add suggestions that are not in the old list and update the existing suggestions.
123         for (Suggestion suggestion : suggestions) {
124             Preference curPref = mainFragment.findPreference(
125                     SuggestionPreference.SUGGESTION_PREFERENCE_KEY + suggestion.getId());
126             if (curPref == null) {
127                 SuggestionPreference newSuggPref =
128                         new SuggestionPreference(suggestion,
129                                 mainFragment.getPreferenceManager().getContext(),
130                                 mSuggestionControllerMixin, mainFragment);
131                 newSuggPref.setIcon(mIconCache.getIcon(suggestion.getIcon()));
132                 newSuggPref.setTitle(suggestion.getTitle());
133                 newSuggPref.setSummary(suggestion.getSummary());
134                 mSuggestionsList.addPreference(newSuggPref);
135             } else {
136                 // Even though the id of suggestion might not change, the details could change.
137                 // So we need to update icon, title and summary for the suggestions.
138                 curPref.setIcon(mIconCache.getIcon(suggestion.getIcon()));
139                 curPref.setTitle(suggestion.getTitle());
140                 curPref.setSummary(suggestion.getSummary());
141             }
142         }
143     }
144 
isRestricted()145     boolean isRestricted() {
146         return SecurityFragment.isRestrictedProfileInEffect(mainFragment.getContext());
147     }
148 
onSuggestionClosed(Preference preference)149     void onSuggestionClosed(Preference preference) {
150         if (mSuggestionsList == null || mSuggestionsList.getPreferenceCount() == 0) {
151             return;
152         } else if (mSuggestionsList.getPreferenceCount() == 1) {
153             mainFragment.getPreferenceScreen().removePreference(mSuggestionsList);
154         } else {
155             mSuggestionsList.removePreference(preference);
156         }
157     }
158 
onHotwordStateChanged()159     void onHotwordStateChanged() {
160         if (mHotwordSwitch != null) {
161             mHotwordSwitchController.updateState(mHotwordSwitch);
162         }
163         showOrHideQuickSettings();
164     }
165 
onHotwordEnable()166     void onHotwordEnable() {
167         try {
168             Intent intent = new Intent(HotwordSwitchController.ACTION_HOTWORD_ENABLE);
169             intent.setPackage(HotwordSwitchController.ASSISTANT_PGK_NAME);
170             mainFragment.startActivityForResult(intent, 0);
171         } catch (ActivityNotFoundException e) {
172             Log.w(TAG, "Unable to find hotwording activity.", e);
173         }
174     }
175 
onHotwordDisable()176     void onHotwordDisable() {
177         try {
178             Intent intent = new Intent(HotwordSwitchController.ACTION_HOTWORD_DISABLE);
179             intent.setPackage(HotwordSwitchController.ASSISTANT_PGK_NAME);
180             mainFragment.startActivityForResult(intent, 0);
181         } catch (ActivityNotFoundException e) {
182             Log.w(TAG, "Unable to find hotwording activity.", e);
183         }
184     }
185 
quickSettingsEnabled()186     private boolean quickSettingsEnabled() {
187         return mainFragment.getContext().getResources().getBoolean(
188                 R.bool.config_quick_settings_enabled);
189     }
190 
191     /** @return true if there is at least one available item in quick settings. */
shouldShowQuickSettings()192     private boolean shouldShowQuickSettings() {
193         for (AbstractPreferenceController controller : mPreferenceControllers) {
194             if (controller.isAvailable()) {
195                 return true;
196             }
197         }
198         return false;
199     }
200 
201 
202     /** Creates the quick settings category and its children. */
showQuickSettings()203     private void showQuickSettings() {
204         if (mQuickSettingsList != null) {
205             return;
206         }
207         mQuickSettingsList = new PreferenceCategory(
208                 mainFragment.getPreferenceManager().getContext());
209         mQuickSettingsList.setKey(KEY_QUICK_SETTINGS);
210         mQuickSettingsList.setTitle(R.string.header_category_quick_settings);
211         mQuickSettingsList.setOrder(1); // at top, but below suggested settings
212         mainFragment.getPreferenceScreen().addPreference(mQuickSettingsList);
213         if (mHotwordSwitchController != null && mHotwordSwitchController.isAvailable()) {
214             mHotwordSwitch = new SwitchWithSoundPreference(
215                     mainFragment.getPreferenceManager().getContext());
216             mHotwordSwitch.setKey(HotwordSwitchController.KEY_HOTWORD_SWITCH);
217             mHotwordSwitch.setOnPreferenceClickListener(preference -> {
218                 logEntrySelected(TvSettingsEnums.QUICK_SETTINGS);
219                 return false;
220             });
221             mHotwordSwitchController.updateState(mHotwordSwitch);
222             mQuickSettingsList.addPreference(mHotwordSwitch);
223         }
224         if (mTakeBugReportController != null && mTakeBugReportController.isAvailable()) {
225             mTakeBugReportPreference = new Preference(
226                     mainFragment.getPreferenceManager().getContext());
227             mTakeBugReportPreference.setKey(TakeBugReportController.KEY_TAKE_BUG_REPORT);
228             mTakeBugReportPreference.setOnPreferenceClickListener(preference -> {
229                 logEntrySelected(TvSettingsEnums.QUICK_SETTINGS);
230                 return false;
231             });
232             mTakeBugReportController.updateState(mTakeBugReportPreference);
233             mQuickSettingsList.addPreference(mTakeBugReportPreference);
234         }
235     }
236 
237     /** Removes the quick settings category and all its children. */
hideQuickSettings()238     private void hideQuickSettings() {
239         Preference quickSettingsPref = mainFragment.findPreference(KEY_QUICK_SETTINGS);
240         if (quickSettingsPref == null) {
241             return;
242         }
243         mQuickSettingsList.removeAll();
244         mainFragment.getPreferenceScreen().removePreference(mQuickSettingsList);
245         mQuickSettingsList = null;
246     }
247 
onCreatePreferenceControllers(Context context)248     List<AbstractPreferenceController> onCreatePreferenceControllers(Context context) {
249         mPreferenceControllers = new ArrayList<>(2);
250         if (quickSettingsEnabled()) {
251             mHotwordSwitchController = new HotwordSwitchController(context);
252             mTakeBugReportController = new TakeBugReportController(context);
253             mPreferenceControllers.add(mHotwordSwitchController);
254             mPreferenceControllers.add(mTakeBugReportController);
255         }
256         return mPreferenceControllers;
257     }
258 
259 }
260