blob: 8da1515325be19b0296d28b545d5624ba62a56a9 [file] [log] [blame]
/*
* 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.tv.settings;
import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_CLASSIC;
import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_TWO_PANEL;
import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_VENDOR;
import static com.android.tv.settings.overlay.FlavorUtils.FLAVOR_X;
import static com.android.tv.settings.util.InstrumentationUtils.logEntrySelected;
import static com.android.tv.settings.util.InstrumentationUtils.logPageFocused;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.tvsettings.TvSettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.service.settings.suggestions.Suggestion;
import android.telephony.SignalStrength;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Keep;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.suggestions.SuggestionControllerMixinCompat;
import com.android.settingslib.utils.IconCache;
import com.android.tv.settings.HotwordSwitchController.HotwordStateListener;
import com.android.tv.settings.accounts.AccountsFragment;
import com.android.tv.settings.connectivity.ConnectivityListener;
import com.android.tv.settings.overlay.FlavorUtils;
import com.android.tv.settings.suggestions.SuggestionPreference;
import com.android.tv.settings.system.SecurityFragment;
import com.android.tv.settings.util.SliceUtils;
import com.android.tv.twopanelsettings.TwoPanelSettingsFragment;
import com.android.tv.twopanelsettings.slices.SlicePreference;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* The fragment where all good things begin. Evil is handled elsewhere.
*/
@Keep
public class MainFragment extends PreferenceControllerFragment implements
SuggestionControllerMixinCompat.SuggestionControllerHost, SuggestionPreference.Callback,
HotwordStateListener {
private static final String TAG = "MainFragment";
private static final String KEY_SUGGESTIONS_LIST = "suggestions";
private static final String KEY_BASIC_MODE_SUGGESTION = "basic_mode_suggestion";
private static final String KEY_BASIC_MODE_EXIT = "basic_mode_exit";
@VisibleForTesting
static final String KEY_ACCOUNTS_AND_SIGN_IN = "accounts_and_sign_in";
@VisibleForTesting
static final String KEY_ACCOUNTS_AND_SIGN_IN_SLICE = "accounts_and_sign_in_slice";
@VisibleForTesting
static final String KEY_ACCOUNTS_AND_SIGN_IN_BASIC_MODE = "accounts_and_sign_in_basic_mode";
private static final String KEY_APPLICATIONS = "applications";
@VisibleForTesting
static final String KEY_ACCESSORIES = "remotes_and_accessories";
@VisibleForTesting
static final String KEY_CONNECTED_DEVICES = "connected_devices";
private static final String KEY_CONNECTED_DEVICES_SLICE = "connected_devices_slice";
@VisibleForTesting
static final String KEY_NETWORK = "network";
@VisibleForTesting
static final String KEY_SOUND = "sound";
public static final String ACTION_SOUND = "com.android.tv.settings.SOUND";
@VisibleForTesting
static final String ACTION_CONNECTED_DEVICES = "com.android.tv.settings.CONNECTED_DEVICES";
@VisibleForTesting
static final String KEY_PRIVACY = "privacy";
@VisibleForTesting
static final String KEY_DISPLAY_AND_SOUND = "display_and_sound";
@VisibleForTesting
static final String KEY_QUICK_SETTINGS = "quick_settings";
private static final String KEY_CHANNELS_AND_INPUTS = "channels_and_inputs";
private static final String ACTION_ACCOUNTS = "com.android.tv.settings.ACCOUNTS";
@VisibleForTesting
ConnectivityListener mConnectivityListener;
@VisibleForTesting
PreferenceCategory mSuggestionsList;
private SuggestionControllerMixinCompat mSuggestionControllerMixin;
@VisibleForTesting
IconCache mIconCache;
@VisibleForTesting
BluetoothAdapter mBtAdapter;
@VisibleForTesting
boolean mHasBtAccessories;
@VisibleForTesting
boolean mHasAccounts;
/** Controllers for the Quick Settings section. */
private List<AbstractPreferenceController> mPreferenceControllers;
private HotwordSwitchController mHotwordSwitchController;
private TakeBugReportController mTakeBugReportController;
private PreferenceCategory mQuickSettingsList;
private SwitchPreference mHotwordSwitch;
private Preference mTakeBugReportPreference;
private final BroadcastReceiver mBCMReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateAccessoryPref();
}
};
public static MainFragment newInstance() {
return new MainFragment();
}
@Override
protected int getPreferenceScreenResId() {
switch (FlavorUtils.getFlavor(getContext())) {
case FLAVOR_CLASSIC:
case FLAVOR_TWO_PANEL:
return R.xml.main_prefs;
case FLAVOR_X:
return R.xml.main_prefs_x;
case FLAVOR_VENDOR:
return R.xml.main_prefs_vendor;
default:
return R.xml.main_prefs;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
mIconCache = new IconCache(getContext());
mConnectivityListener = new ConnectivityListener(getContext(), this::updateConnectivity,
getSettingsLifecycle());
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
super.onCreate(savedInstanceState);
// This is to record the initial start of Settings root in two panel settings case, as the
// MainFragment is the left-most pane and will not be slided in from preview pane. For
// classic settings case, the event will be recorded in onResume() as this is an instance
// of SettingsPreferenceFragment.
if (getCallbackFragment() instanceof TwoPanelSettingsFragment) {
logPageFocused(getPageId(), true);
}
}
@Override
public void onDestroy() {
if (mHotwordSwitchController != null) {
mHotwordSwitchController.unregister();
}
super.onDestroy();
}
private boolean quickSettingsEnabled() {
return getContext().getResources().getBoolean(R.bool.config_quick_settings_enabled);
}
/** @return true if there is at least one available item in quick settings. */
private boolean shouldShowQuickSettings() {
for (AbstractPreferenceController controller : mPreferenceControllers) {
if (controller.isAvailable()) {
return true;
}
}
return false;
}
private void showOrHideQuickSettings() {
if (shouldShowQuickSettings()) {
showQuickSettings();
} else {
hideQuickSettings();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
showOrHideQuickSettings();
updateAccountPref();
updateAccessoryPref();
updateConnectivity();
updateBasicModeSuggestion();
return super.onCreateView(inflater, container, savedInstanceState);
}
/** Creates the quick settings category and its children. */
private void showQuickSettings() {
if (mQuickSettingsList != null) {
return;
}
mQuickSettingsList = new PreferenceCategory(this.getPreferenceManager().getContext());
mQuickSettingsList.setKey(KEY_QUICK_SETTINGS);
mQuickSettingsList.setTitle(R.string.header_category_quick_settings);
mQuickSettingsList.setOrder(1); // at top, but below suggested settings
getPreferenceScreen().addPreference(mQuickSettingsList);
if (mHotwordSwitchController != null && mHotwordSwitchController.isAvailable()) {
mHotwordSwitch = new SwitchPreference(this.getPreferenceManager().getContext());
mHotwordSwitch.setKey(HotwordSwitchController.KEY_HOTWORD_SWITCH);
mHotwordSwitch.setOnPreferenceClickListener(
preference -> {
logEntrySelected(TvSettingsEnums.QUICK_SETTINGS);
return false;
}
);
mHotwordSwitchController.updateState(mHotwordSwitch);
mQuickSettingsList.addPreference(mHotwordSwitch);
}
if (mTakeBugReportController != null && mTakeBugReportController.isAvailable()) {
mTakeBugReportPreference = new Preference(this.getPreferenceManager().getContext());
mTakeBugReportPreference.setKey(TakeBugReportController.KEY_TAKE_BUG_REPORT);
mTakeBugReportPreference.setOnPreferenceClickListener(
preference -> {
logEntrySelected(TvSettingsEnums.QUICK_SETTINGS);
return false;
}
);
mTakeBugReportController.updateState(mTakeBugReportPreference);
mQuickSettingsList.addPreference(mTakeBugReportPreference);
}
}
/** Removes the quick settings category and all its children. */
private void hideQuickSettings() {
Preference quickSettingsPref = findPreference(KEY_QUICK_SETTINGS);
if (quickSettingsPref == null) {
return;
}
mQuickSettingsList.removeAll();
getPreferenceScreen().removePreference(mQuickSettingsList);
mQuickSettingsList = null;
}
@Override
public void onHotwordStateChanged() {
if (mHotwordSwitch != null && mHotwordSwitchController != null) {
mHotwordSwitchController.updateState(mHotwordSwitch);
}
showOrHideQuickSettings();
}
@Override
public void onHotwordEnable() {
try {
Intent intent = new Intent(HotwordSwitchController.ACTION_HOTWORD_ENABLE);
intent.setPackage(HotwordSwitchController.ASSISTANT_PGK_NAME);
startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Unable to find hotwording activity.", e);
}
}
@Override
public void onHotwordDisable() {
try {
Intent intent = new Intent(HotwordSwitchController.ACTION_HOTWORD_DISABLE);
intent.setPackage(HotwordSwitchController.ASSISTANT_PGK_NAME);
startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Unable to find hotwording activity.", e);
}
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(getPreferenceScreenResId(), null);
if (isRestricted()) {
Preference appPref = findPreference(KEY_APPLICATIONS);
if (appPref != null) {
appPref.setVisible(false);
}
Preference accountsPref = findPreference(KEY_ACCOUNTS_AND_SIGN_IN);
if (accountsPref != null) {
accountsPref.setVisible(false);
}
}
if (!supportBluetooth()) {
Preference accessoryPreference = findPreference(KEY_ACCESSORIES);
if (accessoryPreference != null) {
accessoryPreference.setVisible(false);
}
}
if (FlavorUtils.isTwoPanel(getContext())) {
Preference displaySoundPref = findPreference(KEY_DISPLAY_AND_SOUND);
if (displaySoundPref != null) {
displaySoundPref.setVisible(true);
}
Preference privacyPref = findPreference(KEY_PRIVACY);
if (privacyPref != null) {
privacyPref.setVisible(true);
}
}
if (mHotwordSwitchController != null) {
mHotwordSwitchController.init(this);
}
updateSoundSettings();
}
@Override
protected List<AbstractPreferenceController> onCreatePreferenceControllers(Context context) {
mPreferenceControllers = new ArrayList<>(2);
if (quickSettingsEnabled()) {
mHotwordSwitchController = new HotwordSwitchController(context);
mTakeBugReportController = new TakeBugReportController(context);
mPreferenceControllers.add(mHotwordSwitchController);
mPreferenceControllers.add(mTakeBugReportController);
}
return mPreferenceControllers;
}
@VisibleForTesting
void updateConnectivity() {
final Preference networkPref = findPreference(KEY_NETWORK);
if (networkPref == null) {
return;
}
if (mConnectivityListener.isCellConnected()) {
final int signal = mConnectivityListener.getCellSignalStrength();
switch (signal) {
case SignalStrength.SIGNAL_STRENGTH_GREAT:
networkPref.setIcon(R.drawable.ic_cell_signal_4_white);
break;
case SignalStrength.SIGNAL_STRENGTH_GOOD:
networkPref.setIcon(R.drawable.ic_cell_signal_3_white);
break;
case SignalStrength.SIGNAL_STRENGTH_MODERATE:
networkPref.setIcon(R.drawable.ic_cell_signal_2_white);
break;
case SignalStrength.SIGNAL_STRENGTH_POOR:
networkPref.setIcon(R.drawable.ic_cell_signal_1_white);
break;
case SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN:
default:
networkPref.setIcon(R.drawable.ic_cell_signal_0_white);
break;
}
} else if (mConnectivityListener.isEthernetConnected()) {
networkPref.setIcon(R.drawable.ic_ethernet_white);
networkPref.setSummary(R.string.connectivity_summary_ethernet_connected);
} else if (mConnectivityListener.isWifiEnabledOrEnabling()) {
if (mConnectivityListener.isWifiConnected()) {
final int signal = mConnectivityListener.getWifiSignalStrength(5);
switch (signal) {
case 4:
networkPref.setIcon(R.drawable.ic_wifi_signal_4_white);
break;
case 3:
networkPref.setIcon(R.drawable.ic_wifi_signal_3_white);
break;
case 2:
networkPref.setIcon(R.drawable.ic_wifi_signal_2_white);
break;
case 1:
networkPref.setIcon(R.drawable.ic_wifi_signal_1_white);
break;
case 0:
default:
networkPref.setIcon(R.drawable.ic_wifi_signal_0_white);
break;
}
networkPref.setSummary(mConnectivityListener.getSsid());
} else {
networkPref.setIcon(R.drawable.ic_wifi_not_connected);
networkPref.setSummary(R.string.connectivity_summary_no_network_connected);
}
} else {
networkPref.setIcon(R.drawable.ic_wifi_signal_off_white);
networkPref.setSummary(R.string.connectivity_summary_wifi_disabled);
}
}
@VisibleForTesting
void updateSoundSettings() {
final Preference soundPref = findPreference(KEY_SOUND);
if (soundPref != null) {
Intent soundIntent = new Intent(ACTION_SOUND);
final ResolveInfo info = systemIntentIsHandled(getContext(), soundIntent);
soundPref.setVisible(info != null);
if (info != null && info.activityInfo != null) {
String pkgName = info.activityInfo.packageName;
Drawable icon = getDrawableResource(pkgName, "sound_icon");
if (icon != null) {
soundPref.setIcon(icon);
}
String title = getStringResource(pkgName, "sound_pref_title");
if (!TextUtils.isEmpty(title)) {
soundPref.setTitle(title);
}
String summary = getStringResource(pkgName, "sound_pref_summary");
if (!TextUtils.isEmpty(summary)) {
soundPref.setSummary(summary);
}
}
}
}
/**
* Extracts a string resource from a given package.
*
* @param pkgName the package name
* @param resource name, e.g. "my_string_name"
*/
private String getStringResource(String pkgName, String resourceName) {
try {
Context targetContext = getContext().createPackageContext(pkgName, 0);
int resId = targetContext.getResources().getIdentifier(
pkgName + ":string/" + resourceName, null, null);
if (resId != 0) {
return targetContext.getResources().getString(resId);
}
} catch (Resources.NotFoundException | PackageManager.NameNotFoundException
| SecurityException e) {
Log.w(TAG, "Unable to get string resource " + resourceName, e);
}
return null;
}
/**
* Extracts an drawable resource from a given package.
*
* @param pkgName the package name
* @param resource name, e.g. "my_icon_name"
*/
private Drawable getDrawableResource(String pkgName, String resourceName) {
try {
Context targetContext = getContext().createPackageContext(pkgName, 0);
int resId = targetContext.getResources().getIdentifier(
pkgName + ":drawable/" + resourceName, null, null);
if (resId != 0) {
return targetContext.getResources().getDrawable(resId);
}
} catch (Resources.NotFoundException | PackageManager.NameNotFoundException
| SecurityException e) {
Log.w(TAG, "Unable to get drawable resource " + resourceName, e);
}
return null;
}
/**
* Returns the ResolveInfo for the system activity that matches given intent filter or null if
* no such activity exists.
*
* @param context Context of the caller
* @param intent The intent matching the desired system app
* @return ResolveInfo of the matching activity or null if no match exists
*/
public static ResolveInfo systemIntentIsHandled(Context context, Intent intent) {
if (intent == null) {
return null;
}
final PackageManager pm = context.getPackageManager();
for (ResolveInfo info : pm.queryIntentActivities(intent, 0)) {
if (info.activityInfo != null
&& (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
== ApplicationInfo.FLAG_SYSTEM) {
return info;
}
}
return null;
}
private static ProviderInfo getProviderInfo(Context context, String authority) {
return context.getPackageManager().resolveContentProvider(authority, 0);
}
@Override
public void onSuggestionReady(List<Suggestion> data) {
// Suggestion category is handled differently in basic mode
if (data == null || data.size() == 0
|| FlavorUtils.getFeatureFactory(getContext())
.getBasicModeFeatureProvider().isBasicMode(getContext())) {
if (mSuggestionsList != null) {
getPreferenceScreen().removePreference(mSuggestionsList);
mSuggestionsList = null;
}
return;
}
if (mSuggestionsList == null) {
mSuggestionsList = new PreferenceCategory(this.getPreferenceManager().getContext());
mSuggestionsList.setKey(KEY_SUGGESTIONS_LIST);
mSuggestionsList.setTitle(R.string.header_category_suggestions);
mSuggestionsList.setOrder(0); // always at top
getPreferenceScreen().addPreference(mSuggestionsList);
}
updateSuggestionList(data);
}
@VisibleForTesting
void updateSuggestionList(List<Suggestion> suggestions) {
// Remove suggestions that are not in the new list.
for (int i = 0; i < mSuggestionsList.getPreferenceCount(); i++) {
SuggestionPreference pref = (SuggestionPreference) mSuggestionsList.getPreference(i);
boolean isInNewSuggestionList = false;
for (Suggestion suggestion : suggestions) {
if (pref.getId().equals(suggestion.getId())) {
isInNewSuggestionList = true;
break;
}
}
if (!isInNewSuggestionList) {
mSuggestionsList.removePreference(pref);
}
}
// Add suggestions that are not in the old list and update the existing suggestions.
for (Suggestion suggestion : suggestions) {
Preference curPref = findPreference(
SuggestionPreference.SUGGESTION_PREFERENCE_KEY + suggestion.getId());
if (curPref == null) {
SuggestionPreference newSuggPref = new SuggestionPreference(
suggestion, this.getPreferenceManager().getContext(),
mSuggestionControllerMixin, this);
newSuggPref.setIcon(mIconCache.getIcon(suggestion.getIcon()));
newSuggPref.setTitle(suggestion.getTitle());
newSuggPref.setSummary(suggestion.getSummary());
mSuggestionsList.addPreference(newSuggPref);
} else {
// Even though the id of suggestion might not change, the details could change.
// So we need to update icon, title and summary for the suggestions.
curPref.setIcon(mIconCache.getIcon(suggestion.getIcon()));
curPref.setTitle(suggestion.getTitle());
curPref.setSummary(suggestion.getSummary());
}
}
}
private boolean isRestricted() {
return SecurityFragment.isRestrictedProfileInEffect(getContext());
}
@VisibleForTesting
void updateAccessoryPref() {
SlicePreference connectedDevicesSlicePreference =
(SlicePreference) findPreference(KEY_CONNECTED_DEVICES_SLICE);
Preference accessoryPreference = findPreference(KEY_ACCESSORIES);
Preference connectedDevicesPreference = findPreference(KEY_CONNECTED_DEVICES);
if (connectedDevicesSlicePreference != null
&& FlavorUtils.isTwoPanel(getContext())
&& SliceUtils.isSliceProviderValid(
getContext(), connectedDevicesSlicePreference.getUri())) {
connectedDevicesSlicePreference.setVisible(true);
connectedDevicesPreference.setVisible(false);
accessoryPreference.setVisible(false);
ProviderInfo pkgInfo = getProviderInfo(getContext(),
Uri.parse(connectedDevicesSlicePreference.getUri()).getAuthority());
if (pkgInfo != null) {
updateConnectedDevicePref(pkgInfo.packageName, connectedDevicesSlicePreference);
}
return;
}
if (connectedDevicesSlicePreference != null) {
connectedDevicesSlicePreference.setVisible(false);
}
if (connectedDevicesPreference != null) {
Intent intent = new Intent(ACTION_CONNECTED_DEVICES);
ResolveInfo info = systemIntentIsHandled(getContext(), intent);
connectedDevicesPreference.setVisible(info != null);
accessoryPreference.setVisible(info == null);
if (info != null) {
updateConnectedDevicePref(
info.activityInfo.packageName, connectedDevicesPreference);
return;
}
}
if (mBtAdapter == null || accessoryPreference == null) {
return;
}
final Set<BluetoothDevice> bondedDevices = mBtAdapter.getBondedDevices();
mHasBtAccessories = bondedDevices.size() != 0;
}
@VisibleForTesting
void updateAccountPref() {
Preference accountsPref = findPreference(KEY_ACCOUNTS_AND_SIGN_IN);
SlicePreference accountsSlicePref =
(SlicePreference) findPreference(KEY_ACCOUNTS_AND_SIGN_IN_SLICE);
Preference accountsBasicMode = findPreference(KEY_ACCOUNTS_AND_SIGN_IN_BASIC_MODE);
Intent intent = new Intent(ACTION_ACCOUNTS);
if (FlavorUtils.getFeatureFactory(getContext()).getBasicModeFeatureProvider()
.isBasicMode(getContext())) {
if (accountsBasicMode != null) {
accountsBasicMode.setVisible(true);
}
if (accountsPref != null) {
accountsPref.setVisible(false);
}
if (accountsSlicePref != null) {
accountsSlicePref.setVisible(false);
}
return;
} else {
if (accountsBasicMode != null) {
accountsBasicMode.setVisible(false);
}
}
// If the intent can be handled, use it.
if (systemIntentIsHandled(getContext(), intent) != null) {
accountsPref.setVisible(true);
accountsPref.setFragment(null);
accountsPref.setIntent(intent);
accountsSlicePref.setVisible(false);
return;
}
// If a slice is available, use it to display the accounts settings, otherwise fall back to
// use AccountsFragment.
String uri = accountsSlicePref.getUri();
if (SliceUtils.isSliceProviderValid(getContext(), uri)) {
accountsPref.setVisible(false);
accountsSlicePref.setVisible(true);
} else {
accountsPref.setVisible(true);
accountsSlicePref.setVisible(false);
updateAccountPrefInfo();
}
}
@VisibleForTesting
void updateAccountPrefInfo() {
Preference accountsPref = findPreference(KEY_ACCOUNTS_AND_SIGN_IN);
if (accountsPref != null && accountsPref.isVisible()) {
final AccountManager am = AccountManager.get(getContext());
Account[] accounts = am.getAccounts();
if (accounts.length == 0) {
mHasAccounts = false;
accountsPref.setIcon(R.drawable.ic_add_an_account);
accountsPref.setSummary(R.string.accounts_category_summary_no_account);
AccountsFragment.setUpAddAccountPrefIntent(accountsPref, getContext());
} else {
mHasAccounts = true;
accountsPref.setIcon(R.drawable.ic_accounts_and_sign_in);
if (accounts.length == 1) {
accountsPref.setSummary(accounts[0].name);
} else {
accountsPref.setSummary(getResources().getQuantityString(
R.plurals.accounts_category_summary, accounts.length, accounts.length));
}
}
}
}
@VisibleForTesting
void updateBasicModeSuggestion() {
PreferenceCategory basicModeSuggestion = findPreference(KEY_BASIC_MODE_SUGGESTION);
if (basicModeSuggestion == null) {
return;
}
if (FlavorUtils.getFeatureFactory(getContext())
.getBasicModeFeatureProvider().isBasicMode(getContext())) {
basicModeSuggestion.setVisible(true);
} else {
basicModeSuggestion.setVisible(false);
}
}
@Override
public void onStart() {
super.onStart();
IntentFilter btChangeFilter = new IntentFilter();
btChangeFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
btChangeFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
btChangeFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
getContext().registerReceiver(mBCMReceiver, btChangeFilter);
}
@Override
public void onStop() {
super.onStop();
getContext().unregisterReceiver(mBCMReceiver);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
ComponentName componentName = new ComponentName(
"com.android.settings.intelligence",
"com.android.settings.intelligence.suggestions.SuggestionService");
if (!isRestricted()) {
mSuggestionControllerMixin = new SuggestionControllerMixinCompat(
context, this, getSettingsLifecycle(), componentName);
}
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (preference.getKey().equals(KEY_ACCOUNTS_AND_SIGN_IN) && !mHasAccounts
|| (preference.getKey().equals(KEY_ACCESSORIES) && !mHasBtAccessories)
|| (preference.getKey().equals(KEY_DISPLAY_AND_SOUND)
&& preference.getIntent() != null)
|| (preference.getKey().equals(KEY_CHANNELS_AND_INPUTS)
&& preference.getIntent() != null)) {
getContext().startActivity(preference.getIntent());
return true;
} else if (preference.getKey().equals(KEY_BASIC_MODE_EXIT)
&& FlavorUtils.getFeatureFactory(getContext())
.getBasicModeFeatureProvider().isBasicMode(getContext())) {
if (getActivity() != null) {
FlavorUtils.getFeatureFactory(getContext())
.getBasicModeFeatureProvider().startBasicModeExitActivity(getActivity());
}
return true;
} else {
return super.onPreferenceTreeClick(preference);
}
}
@Override
public void onSuggestionClosed(Preference preference) {
if (mSuggestionsList == null || mSuggestionsList.getPreferenceCount() == 0) {
return;
} else if (mSuggestionsList.getPreferenceCount() == 1) {
getPreferenceScreen().removePreference(mSuggestionsList);
} else {
mSuggestionsList.removePreference(preference);
}
}
private boolean supportBluetooth() {
return getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
}
private void updateConnectedDevicePref(String pkgName, Preference pref) {
Drawable icon = getDrawableResource(pkgName, "connected_devices_pref_icon");
if (icon != null) {
pref.setIcon(icon);
}
String title =
(pref instanceof SlicePreference)
? getStringResource(pkgName, "connected_devices_slice_pref_title")
: getStringResource(pkgName, "connected_devices_pref_title");
if (!TextUtils.isEmpty(title)) {
pref.setTitle(title);
}
String summary = getStringResource(pkgName, "connected_devices_pref_summary");
if (!TextUtils.isEmpty(summary)) {
pref.setSummary(summary);
}
pref.setOnPreferenceClickListener(
preference -> {
logEntrySelected(TvSettingsEnums.CONNECTED_CLASSIC);
return false;
});
}
@Override
protected int getPageId() {
return TvSettingsEnums.TV_SETTINGS_ROOT;
}
}