Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2014 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;
     18 
     19 import android.app.ActionBar;
     20 import android.app.Activity;
     21 import android.app.Fragment;
     22 import android.app.FragmentManager;
     23 import android.app.FragmentTransaction;
     24 import android.content.BroadcastReceiver;
     25 import android.content.ComponentName;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.content.SharedPreferences;
     30 import android.content.pm.ActivityInfo;
     31 import android.content.pm.PackageManager;
     32 import android.content.pm.PackageManager.NameNotFoundException;
     33 import android.content.pm.ResolveInfo;
     34 import android.content.res.Configuration;
     35 import android.content.res.TypedArray;
     36 import android.content.res.XmlResourceParser;
     37 import android.nfc.NfcAdapter;
     38 import android.os.Bundle;
     39 import android.os.Handler;
     40 import android.os.INetworkManagementService;
     41 import android.os.Message;
     42 import android.os.RemoteException;
     43 import android.os.ServiceManager;
     44 import android.os.UserHandle;
     45 import android.os.UserManager;
     46 import android.preference.Preference;
     47 import android.preference.PreferenceFragment;
     48 import android.preference.PreferenceManager;
     49 import android.preference.PreferenceScreen;
     50 import android.text.TextUtils;
     51 import android.transition.TransitionManager;
     52 import android.util.AttributeSet;
     53 import android.util.Log;
     54 import android.util.TypedValue;
     55 import android.util.Xml;
     56 import android.view.Menu;
     57 import android.view.MenuInflater;
     58 import android.view.MenuItem;
     59 import android.view.View;
     60 import android.view.View.OnClickListener;
     61 import android.view.ViewGroup;
     62 import android.widget.Button;
     63 import android.widget.SearchView;
     64 
     65 import com.android.internal.util.ArrayUtils;
     66 import com.android.internal.util.XmlUtils;
     67 import com.android.settings.accessibility.AccessibilitySettings;
     68 import com.android.settings.accessibility.CaptionPropertiesFragment;
     69 import com.android.settings.accounts.AccountSettings;
     70 import com.android.settings.accounts.AccountSyncSettings;
     71 import com.android.settings.applications.InstalledAppDetails;
     72 import com.android.settings.applications.ManageApplications;
     73 import com.android.settings.applications.ProcessStatsUi;
     74 import com.android.settings.bluetooth.BluetoothSettings;
     75 import com.android.settings.dashboard.DashboardCategory;
     76 import com.android.settings.dashboard.DashboardSummary;
     77 import com.android.settings.dashboard.DashboardTile;
     78 import com.android.settings.dashboard.NoHomeDialogFragment;
     79 import com.android.settings.dashboard.SearchResultsSummary;
     80 import com.android.settings.deviceinfo.Memory;
     81 import com.android.settings.deviceinfo.UsbSettings;
     82 import com.android.settings.fuelgauge.BatterySaverSettings;
     83 import com.android.settings.fuelgauge.PowerUsageSummary;
     84 import com.android.settings.notification.NotificationAppList;
     85 import com.android.settings.notification.OtherSoundSettings;
     86 import com.android.settings.quicklaunch.QuickLaunchSettings;
     87 import com.android.settings.search.DynamicIndexableContentMonitor;
     88 import com.android.settings.search.Index;
     89 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
     90 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
     91 import com.android.settings.inputmethod.SpellCheckersSettings;
     92 import com.android.settings.inputmethod.UserDictionaryList;
     93 import com.android.settings.location.LocationSettings;
     94 import com.android.settings.nfc.AndroidBeam;
     95 import com.android.settings.nfc.PaymentSettings;
     96 import com.android.settings.notification.AppNotificationSettings;
     97 import com.android.settings.notification.ConditionProviderSettings;
     98 import com.android.settings.notification.NotificationAccessSettings;
     99 import com.android.settings.notification.NotificationSettings;
    100 import com.android.settings.notification.NotificationStation;
    101 import com.android.settings.notification.ZenModeSettings;
    102 import com.android.settings.print.PrintJobSettingsFragment;
    103 import com.android.settings.print.PrintSettingsFragment;
    104 import com.android.settings.sim.SimSettings;
    105 import com.android.settings.tts.TextToSpeechSettings;
    106 import com.android.settings.users.UserSettings;
    107 import com.android.settings.voice.VoiceInputSettings;
    108 import com.android.settings.vpn2.VpnSettings;
    109 import com.android.settings.wfd.WifiDisplaySettings;
    110 import com.android.settings.widget.SwitchBar;
    111 import com.android.settings.wifi.AdvancedWifiSettings;
    112 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
    113 import com.android.settings.wifi.WifiSettings;
    114 import com.android.settings.wifi.p2p.WifiP2pSettings;
    115 
    116 import org.xmlpull.v1.XmlPullParser;
    117 import org.xmlpull.v1.XmlPullParserException;
    118 
    119 import java.io.IOException;
    120 import java.util.ArrayList;
    121 import java.util.List;
    122 import java.util.Set;
    123 
    124 import static com.android.settings.dashboard.DashboardTile.TILE_ID_UNDEFINED;
    125 
    126 public class SettingsActivity extends Activity
    127         implements PreferenceManager.OnPreferenceTreeClickListener,
    128         PreferenceFragment.OnPreferenceStartFragmentCallback,
    129         ButtonBarHandler, FragmentManager.OnBackStackChangedListener,
    130         SearchView.OnQueryTextListener, SearchView.OnCloseListener,
    131         MenuItem.OnActionExpandListener {
    132 
    133     private static final String LOG_TAG = "Settings";
    134 
    135     // Constants for state save/restore
    136     private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
    137     private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
    138     private static final String SAVE_KEY_SEARCH_QUERY = ":settings:search_query";
    139     private static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
    140     private static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search";
    141     private static final String SAVE_KEY_HOME_ACTIVITIES_COUNT = ":settings:home_activities_count";
    142 
    143     /**
    144      * When starting this activity, the invoking Intent can contain this extra
    145      * string to specify which fragment should be initially displayed.
    146      * <p/>Starting from Key Lime Pie, when this argument is passed in, the activity
    147      * will call isValidFragment() to confirm that the fragment class name is valid for this
    148      * activity.
    149      */
    150     public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
    151 
    152     /**
    153      * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
    154      * this extra can also be specified to supply a Bundle of arguments to pass
    155      * to that fragment when it is instantiated during the initial creation
    156      * of the activity.
    157      */
    158     public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
    159 
    160     /**
    161      * Fragment "key" argument passed thru {@link #EXTRA_SHOW_FRAGMENT_ARGUMENTS}
    162      */
    163     public static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
    164 
    165     public static final String BACK_STACK_PREFS = ":settings:prefs";
    166 
    167     // extras that allow any preference activity to be launched as part of a wizard
    168 
    169     // show Back and Next buttons? takes boolean parameter
    170     // Back will then return RESULT_CANCELED and Next RESULT_OK
    171     protected static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
    172 
    173     // add a Skip button?
    174     private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
    175 
    176     // specify custom text for the Back or Next buttons, or cause a button to not appear
    177     // at all by setting it to null
    178     protected static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
    179     protected static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
    180 
    181     /**
    182      * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
    183      * those extra can also be specify to supply the title or title res id to be shown for
    184      * that fragment.
    185      */
    186     public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
    187     public static final String EXTRA_SHOW_FRAGMENT_TITLE_RESID =
    188             ":settings:show_fragment_title_resid";
    189     public static final String EXTRA_SHOW_FRAGMENT_AS_SHORTCUT =
    190             ":settings:show_fragment_as_shortcut";
    191 
    192     public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
    193             ":settings:show_fragment_as_subsetting";
    194 
    195     private static final String META_DATA_KEY_FRAGMENT_CLASS =
    196         "com.android.settings.FRAGMENT_CLASS";
    197 
    198     private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
    199 
    200     private static final String EMPTY_QUERY = "";
    201 
    202     private static boolean sShowNoHomeNotice = false;
    203 
    204     private String mFragmentClass;
    205 
    206     private CharSequence mInitialTitle;
    207     private int mInitialTitleResId;
    208 
    209     // Show only these settings for restricted users
    210     private int[] SETTINGS_FOR_RESTRICTED = {
    211             R.id.wireless_section,
    212             R.id.wifi_settings,
    213             R.id.bluetooth_settings,
    214             R.id.data_usage_settings,
    215             R.id.sim_settings,
    216             R.id.wireless_settings,
    217             R.id.device_section,
    218             R.id.notification_settings,
    219             R.id.display_settings,
    220             R.id.storage_settings,
    221             R.id.application_settings,
    222             R.id.battery_settings,
    223             R.id.personal_section,
    224             R.id.location_settings,
    225             R.id.security_settings,
    226             R.id.language_settings,
    227             R.id.user_settings,
    228             R.id.account_settings,
    229             R.id.system_section,
    230             R.id.date_time_settings,
    231             R.id.about_settings,
    232             R.id.accessibility_settings,
    233             R.id.print_settings,
    234             R.id.nfc_payment_settings,
    235             R.id.home_settings,
    236             R.id.dashboard
    237     };
    238 
    239     private static final String[] ENTRY_FRAGMENTS = {
    240             WirelessSettings.class.getName(),
    241             WifiSettings.class.getName(),
    242             AdvancedWifiSettings.class.getName(),
    243             SavedAccessPointsWifiSettings.class.getName(),
    244             BluetoothSettings.class.getName(),
    245             SimSettings.class.getName(),
    246             TetherSettings.class.getName(),
    247             WifiP2pSettings.class.getName(),
    248             VpnSettings.class.getName(),
    249             DateTimeSettings.class.getName(),
    250             LocalePicker.class.getName(),
    251             InputMethodAndLanguageSettings.class.getName(),
    252             VoiceInputSettings.class.getName(),
    253             SpellCheckersSettings.class.getName(),
    254             UserDictionaryList.class.getName(),
    255             UserDictionarySettings.class.getName(),
    256             HomeSettings.class.getName(),
    257             DisplaySettings.class.getName(),
    258             DeviceInfoSettings.class.getName(),
    259             ManageApplications.class.getName(),
    260             ProcessStatsUi.class.getName(),
    261             NotificationStation.class.getName(),
    262             LocationSettings.class.getName(),
    263             SecuritySettings.class.getName(),
    264             UsageAccessSettings.class.getName(),
    265             PrivacySettings.class.getName(),
    266             DeviceAdminSettings.class.getName(),
    267             AccessibilitySettings.class.getName(),
    268             CaptionPropertiesFragment.class.getName(),
    269             com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment.class.getName(),
    270             TextToSpeechSettings.class.getName(),
    271             Memory.class.getName(),
    272             DevelopmentSettings.class.getName(),
    273             UsbSettings.class.getName(),
    274             AndroidBeam.class.getName(),
    275             WifiDisplaySettings.class.getName(),
    276             PowerUsageSummary.class.getName(),
    277             AccountSyncSettings.class.getName(),
    278             AccountSettings.class.getName(),
    279             CryptKeeperSettings.class.getName(),
    280             DataUsageSummary.class.getName(),
    281             DreamSettings.class.getName(),
    282             UserSettings.class.getName(),
    283             NotificationAccessSettings.class.getName(),
    284             ConditionProviderSettings.class.getName(),
    285             PrintSettingsFragment.class.getName(),
    286             PrintJobSettingsFragment.class.getName(),
    287             TrustedCredentialsSettings.class.getName(),
    288             PaymentSettings.class.getName(),
    289             KeyboardLayoutPickerFragment.class.getName(),
    290             ZenModeSettings.class.getName(),
    291             NotificationSettings.class.getName(),
    292             ChooseLockPassword.ChooseLockPasswordFragment.class.getName(),
    293             ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
    294             InstalledAppDetails.class.getName(),
    295             BatterySaverSettings.class.getName(),
    296             NotificationAppList.class.getName(),
    297             AppNotificationSettings.class.getName(),
    298             OtherSoundSettings.class.getName(),
    299             QuickLaunchSettings.class.getName(),
    300             ApnSettings.class.getName()
    301     };
    302 
    303 
    304     private static final String[] LIKE_SHORTCUT_INTENT_ACTION_ARRAY = {
    305             "android.settings.APPLICATION_DETAILS_SETTINGS"
    306     };
    307 
    308     private SharedPreferences mDevelopmentPreferences;
    309     private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
    310 
    311     private boolean mBatteryPresent = true;
    312     private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
    313         @Override
    314         public void onReceive(Context context, Intent intent) {
    315             String action = intent.getAction();
    316             if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
    317                 boolean batteryPresent = Utils.isBatteryPresent(intent);
    318 
    319                 if (mBatteryPresent != batteryPresent) {
    320                     mBatteryPresent = batteryPresent;
    321                     invalidateCategories(true);
    322                 }
    323             }
    324         }
    325     };
    326 
    327     private final DynamicIndexableContentMonitor mDynamicIndexableContentMonitor =
    328             new DynamicIndexableContentMonitor();
    329 
    330     private ActionBar mActionBar;
    331     private SwitchBar mSwitchBar;
    332 
    333     private Button mNextButton;
    334 
    335     private boolean mDisplayHomeAsUpEnabled;
    336     private boolean mDisplaySearch;
    337 
    338     private boolean mIsShowingDashboard;
    339     private boolean mIsShortcut;
    340 
    341     private ViewGroup mContent;
    342 
    343     private SearchView mSearchView;
    344     private MenuItem mSearchMenuItem;
    345     private boolean mSearchMenuItemExpanded = false;
    346     private SearchResultsSummary mSearchResultsFragment;
    347     private String mSearchQuery;
    348 
    349     // Categories
    350     private ArrayList<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
    351 
    352     private static final String MSG_DATA_FORCE_REFRESH = "msg_data_force_refresh";
    353     private static final int MSG_BUILD_CATEGORIES = 1;
    354     private Handler mHandler = new Handler() {
    355         @Override
    356         public void handleMessage(Message msg) {
    357             switch (msg.what) {
    358                 case MSG_BUILD_CATEGORIES: {
    359                     final boolean forceRefresh = msg.getData().getBoolean(MSG_DATA_FORCE_REFRESH);
    360                     if (forceRefresh) {
    361                         buildDashboardCategories(mCategories);
    362                     }
    363                 } break;
    364             }
    365         }
    366     };
    367 
    368     private boolean mNeedToRevertToInitialFragment = false;
    369     private int mHomeActivitiesCount = 1;
    370 
    371     private Intent mResultIntentData;
    372 
    373     public SwitchBar getSwitchBar() {
    374         return mSwitchBar;
    375     }
    376 
    377     public List<DashboardCategory> getDashboardCategories(boolean forceRefresh) {
    378         if (forceRefresh || mCategories.size() == 0) {
    379             buildDashboardCategories(mCategories);
    380         }
    381         return mCategories;
    382     }
    383 
    384     @Override
    385     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
    386         // Override the fragment title for Wallpaper settings
    387         int titleRes = pref.getTitleRes();
    388         if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
    389             titleRes = R.string.wallpaper_settings_fragment_title;
    390         } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
    391                 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
    392             if (UserManager.get(this).isLinkedUser()) {
    393                 titleRes = R.string.profile_info_settings_title;
    394             } else {
    395                 titleRes = R.string.user_info_settings_title;
    396             }
    397         }
    398         startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
    399                 null, 0);
    400         return true;
    401     }
    402 
    403     @Override
    404     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
    405         return false;
    406     }
    407 
    408     private void invalidateCategories(boolean forceRefresh) {
    409         if (!mHandler.hasMessages(MSG_BUILD_CATEGORIES)) {
    410             Message msg = new Message();
    411             msg.what = MSG_BUILD_CATEGORIES;
    412             msg.getData().putBoolean(MSG_DATA_FORCE_REFRESH, forceRefresh);
    413         }
    414     }
    415 
    416     @Override
    417     public void onConfigurationChanged(Configuration newConfig) {
    418         super.onConfigurationChanged(newConfig);
    419         Index.getInstance(this).update();
    420     }
    421 
    422     @Override
    423     protected void onStart() {
    424         super.onStart();
    425 
    426         if (mNeedToRevertToInitialFragment) {
    427             revertToInitialFragment();
    428         }
    429     }
    430 
    431     @Override
    432     public boolean onCreateOptionsMenu(Menu menu) {
    433         if (!mDisplaySearch) {
    434             return false;
    435         }
    436 
    437         MenuInflater inflater = getMenuInflater();
    438         inflater.inflate(R.menu.options_menu, menu);
    439 
    440         // Cache the search query (can be overriden by the OnQueryTextListener)
    441         final String query = mSearchQuery;
    442 
    443         mSearchMenuItem = menu.findItem(R.id.search);
    444         mSearchView = (SearchView) mSearchMenuItem.getActionView();
    445 
    446         if (mSearchMenuItem == null || mSearchView == null) {
    447             return false;
    448         }
    449 
    450         if (mSearchResultsFragment != null) {
    451             mSearchResultsFragment.setSearchView(mSearchView);
    452         }
    453 
    454         mSearchMenuItem.setOnActionExpandListener(this);
    455         mSearchView.setOnQueryTextListener(this);
    456         mSearchView.setOnCloseListener(this);
    457 
    458         if (mSearchMenuItemExpanded) {
    459             mSearchMenuItem.expandActionView();
    460         }
    461         mSearchView.setQuery(query, true /* submit */);
    462 
    463         return true;
    464     }
    465 
    466     private static boolean isShortCutIntent(final Intent intent) {
    467         Set<String> categories = intent.getCategories();
    468         return (categories != null) && categories.contains("com.android.settings.SHORTCUT");
    469     }
    470 
    471     private static boolean isLikeShortCutIntent(final Intent intent) {
    472         String action = intent.getAction();
    473         if (action == null) {
    474             return false;
    475         }
    476         for (int i = 0; i < LIKE_SHORTCUT_INTENT_ACTION_ARRAY.length; i++) {
    477             if (LIKE_SHORTCUT_INTENT_ACTION_ARRAY[i].equals(action)) return true;
    478         }
    479         return false;
    480     }
    481 
    482     @Override
    483     protected void onCreate(Bundle savedState) {
    484         super.onCreate(savedState);
    485 
    486         // Should happen before any call to getIntent()
    487         getMetaData();
    488 
    489         final Intent intent = getIntent();
    490         if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
    491             getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
    492         }
    493 
    494         mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
    495                 Context.MODE_PRIVATE);
    496 
    497         // Getting Intent properties can only be done after the super.onCreate(...)
    498         final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
    499 
    500         mIsShortcut = isShortCutIntent(intent) || isLikeShortCutIntent(intent) ||
    501                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, false);
    502 
    503         final ComponentName cn = intent.getComponent();
    504         final String className = cn.getClassName();
    505 
    506         mIsShowingDashboard = className.equals(Settings.class.getName());
    507 
    508         // This is a "Sub Settings" when:
    509         // - this is a real SubSettings
    510         // - or :settings:show_fragment_as_subsetting is passed to the Intent
    511         final boolean isSubSettings = className.equals(SubSettings.class.getName()) ||
    512                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
    513 
    514         // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content insets
    515         if (isSubSettings) {
    516             // Check also that we are not a Theme Dialog as we don't want to override them
    517             final int themeResId = getThemeResId();
    518             if (themeResId != R.style.Theme_DialogWhenLarge &&
    519                     themeResId != R.style.Theme_SubSettingsDialogWhenLarge) {
    520                 setTheme(R.style.Theme_SubSettings);
    521             }
    522         }
    523 
    524         setContentView(mIsShowingDashboard ?
    525                 R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
    526 
    527         mContent = (ViewGroup) findViewById(R.id.main_content);
    528 
    529         getFragmentManager().addOnBackStackChangedListener(this);
    530 
    531         if (mIsShowingDashboard) {
    532             Index.getInstance(getApplicationContext()).update();
    533         }
    534 
    535         if (savedState != null) {
    536             // We are restarting from a previous saved state; used that to initialize, instead
    537             // of starting fresh.
    538             mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
    539             mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
    540 
    541             setTitleFromIntent(intent);
    542 
    543             ArrayList<DashboardCategory> categories =
    544                     savedState.getParcelableArrayList(SAVE_KEY_CATEGORIES);
    545             if (categories != null) {
    546                 mCategories.clear();
    547                 mCategories.addAll(categories);
    548                 setTitleFromBackStack();
    549             }
    550 
    551             mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
    552             mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
    553             mHomeActivitiesCount = savedState.getInt(SAVE_KEY_HOME_ACTIVITIES_COUNT,
    554                     1 /* one home activity by default */);
    555         } else {
    556             if (!mIsShowingDashboard) {
    557                 // Search is shown we are launched thru a Settings "shortcut". UP will be shown
    558                 // only if it is a sub settings
    559                 if (mIsShortcut) {
    560                     mDisplayHomeAsUpEnabled = isSubSettings;
    561                     mDisplaySearch = false;
    562                 } else if (isSubSettings) {
    563                     mDisplayHomeAsUpEnabled = true;
    564                     mDisplaySearch = true;
    565                 } else {
    566                     mDisplayHomeAsUpEnabled = false;
    567                     mDisplaySearch = false;
    568                 }
    569                 setTitleFromIntent(intent);
    570 
    571                 Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
    572                 switchToFragment(initialFragmentName, initialArguments, true, false,
    573                         mInitialTitleResId, mInitialTitle, false);
    574             } else {
    575                 // No UP affordance if we are displaying the main Dashboard
    576                 mDisplayHomeAsUpEnabled = false;
    577                 // Show Search affordance
    578                 mDisplaySearch = true;
    579                 mInitialTitleResId = R.string.dashboard_title;
    580                 switchToFragment(DashboardSummary.class.getName(), null, false, false,
    581                         mInitialTitleResId, mInitialTitle, false);
    582             }
    583         }
    584 
    585         mActionBar = getActionBar();
    586         if (mActionBar != null) {
    587             mActionBar.setDisplayHomeAsUpEnabled(mDisplayHomeAsUpEnabled);
    588             mActionBar.setHomeButtonEnabled(mDisplayHomeAsUpEnabled);
    589         }
    590         mSwitchBar = (SwitchBar) findViewById(R.id.switch_bar);
    591 
    592         // see if we should show Back/Next buttons
    593         if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
    594 
    595             View buttonBar = findViewById(R.id.button_bar);
    596             if (buttonBar != null) {
    597                 buttonBar.setVisibility(View.VISIBLE);
    598 
    599                 Button backButton = (Button)findViewById(R.id.back_button);
    600                 backButton.setOnClickListener(new OnClickListener() {
    601                     public void onClick(View v) {
    602                         setResult(RESULT_CANCELED, getResultIntentData());
    603                         finish();
    604                     }
    605                 });
    606                 Button skipButton = (Button)findViewById(R.id.skip_button);
    607                 skipButton.setOnClickListener(new OnClickListener() {
    608                     public void onClick(View v) {
    609                         setResult(RESULT_OK, getResultIntentData());
    610                         finish();
    611                     }
    612                 });
    613                 mNextButton = (Button)findViewById(R.id.next_button);
    614                 mNextButton.setOnClickListener(new OnClickListener() {
    615                     public void onClick(View v) {
    616                         setResult(RESULT_OK, getResultIntentData());
    617                         finish();
    618                     }
    619                 });
    620 
    621                 // set our various button parameters
    622                 if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
    623                     String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
    624                     if (TextUtils.isEmpty(buttonText)) {
    625                         mNextButton.setVisibility(View.GONE);
    626                     }
    627                     else {
    628                         mNextButton.setText(buttonText);
    629                     }
    630                 }
    631                 if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
    632                     String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
    633                     if (TextUtils.isEmpty(buttonText)) {
    634                         backButton.setVisibility(View.GONE);
    635                     }
    636                     else {
    637                         backButton.setText(buttonText);
    638                     }
    639                 }
    640                 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
    641                     skipButton.setVisibility(View.VISIBLE);
    642                 }
    643             }
    644         }
    645 
    646         mHomeActivitiesCount = getHomeActivitiesCount();
    647     }
    648 
    649     private int getHomeActivitiesCount() {
    650         final ArrayList<ResolveInfo> homeApps = new ArrayList<ResolveInfo>();
    651         getPackageManager().getHomeActivities(homeApps);
    652         return homeApps.size();
    653     }
    654 
    655     private void setTitleFromIntent(Intent intent) {
    656         final int initialTitleResId = intent.getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
    657         if (initialTitleResId > 0) {
    658             mInitialTitle = null;
    659             mInitialTitleResId = initialTitleResId;
    660             setTitle(mInitialTitleResId);
    661         } else {
    662             mInitialTitleResId = -1;
    663             final String initialTitle = intent.getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE);
    664             mInitialTitle = (initialTitle != null) ? initialTitle : getTitle();
    665             setTitle(mInitialTitle);
    666         }
    667     }
    668 
    669     @Override
    670     public void onBackStackChanged() {
    671         setTitleFromBackStack();
    672     }
    673 
    674     private int setTitleFromBackStack() {
    675         final int count = getFragmentManager().getBackStackEntryCount();
    676 
    677         if (count == 0) {
    678             if (mInitialTitleResId > 0) {
    679                 setTitle(mInitialTitleResId);
    680             } else {
    681                 setTitle(mInitialTitle);
    682             }
    683             return 0;
    684         }
    685 
    686         FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
    687         setTitleFromBackStackEntry(bse);
    688 
    689         return count;
    690     }
    691 
    692     private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) {
    693         final CharSequence title;
    694         final int titleRes = bse.getBreadCrumbTitleRes();
    695         if (titleRes > 0) {
    696             title = getText(titleRes);
    697         } else {
    698             title = bse.getBreadCrumbTitle();
    699         }
    700         if (title != null) {
    701             setTitle(title);
    702         }
    703     }
    704 
    705     @Override
    706     protected void onSaveInstanceState(Bundle outState) {
    707         super.onSaveInstanceState(outState);
    708 
    709         if (mCategories.size() > 0) {
    710             outState.putParcelableArrayList(SAVE_KEY_CATEGORIES, mCategories);
    711         }
    712 
    713         outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled);
    714         outState.putBoolean(SAVE_KEY_SHOW_SEARCH, mDisplaySearch);
    715 
    716         if (mDisplaySearch) {
    717             // The option menus are created if the ActionBar is visible and they are also created
    718             // asynchronously. If you launch Settings with an Intent action like
    719             // android.intent.action.POWER_USAGE_SUMMARY and at the same time your device is locked
    720             // thru a LockScreen, onCreateOptionsMenu() is not yet called and references to the search
    721             // menu item and search view are null.
    722             boolean isExpanded = (mSearchMenuItem != null) && mSearchMenuItem.isActionViewExpanded();
    723             outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, isExpanded);
    724 
    725             String query = (mSearchView != null) ? mSearchView.getQuery().toString() : EMPTY_QUERY;
    726             outState.putString(SAVE_KEY_SEARCH_QUERY, query);
    727         }
    728 
    729         outState.putInt(SAVE_KEY_HOME_ACTIVITIES_COUNT, mHomeActivitiesCount);
    730     }
    731 
    732     @Override
    733     public void onResume() {
    734         super.onResume();
    735 
    736         final int newHomeActivityCount = getHomeActivitiesCount();
    737         if (newHomeActivityCount != mHomeActivitiesCount) {
    738             mHomeActivitiesCount = newHomeActivityCount;
    739             invalidateCategories(true);
    740         }
    741 
    742         mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
    743             @Override
    744             public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    745                 invalidateCategories(true);
    746             }
    747         };
    748         mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
    749                 mDevelopmentPreferencesListener);
    750 
    751         registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    752 
    753         mDynamicIndexableContentMonitor.register(this);
    754 
    755         if(mDisplaySearch && !TextUtils.isEmpty(mSearchQuery)) {
    756             onQueryTextSubmit(mSearchQuery);
    757         }
    758     }
    759 
    760     @Override
    761     public void onPause() {
    762         super.onPause();
    763 
    764         unregisterReceiver(mBatteryInfoReceiver);
    765         mDynamicIndexableContentMonitor.unregister();
    766     }
    767 
    768     @Override
    769     public void onDestroy() {
    770         super.onDestroy();
    771 
    772         mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
    773                 mDevelopmentPreferencesListener);
    774         mDevelopmentPreferencesListener = null;
    775     }
    776 
    777     protected boolean isValidFragment(String fragmentName) {
    778         // Almost all fragments are wrapped in this,
    779         // except for a few that have their own activities.
    780         for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
    781             if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
    782         }
    783         return false;
    784     }
    785 
    786     @Override
    787     public Intent getIntent() {
    788         Intent superIntent = super.getIntent();
    789         String startingFragment = getStartingFragmentClass(superIntent);
    790         // This is called from super.onCreate, isMultiPane() is not yet reliable
    791         // Do not use onIsHidingHeaders either, which relies itself on this method
    792         if (startingFragment != null) {
    793             Intent modIntent = new Intent(superIntent);
    794             modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
    795             Bundle args = superIntent.getExtras();
    796             if (args != null) {
    797                 args = new Bundle(args);
    798             } else {
    799                 args = new Bundle();
    800             }
    801             args.putParcelable("intent", superIntent);
    802             modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
    803             return modIntent;
    804         }
    805         return superIntent;
    806     }
    807 
    808     /**
    809      * Checks if the component name in the intent is different from the Settings class and
    810      * returns the class name to load as a fragment.
    811      */
    812     private String getStartingFragmentClass(Intent intent) {
    813         if (mFragmentClass != null) return mFragmentClass;
    814 
    815         String intentClass = intent.getComponent().getClassName();
    816         if (intentClass.equals(getClass().getName())) return null;
    817 
    818         if ("com.android.settings.ManageApplications".equals(intentClass)
    819                 || "com.android.settings.RunningServices".equals(intentClass)
    820                 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
    821             // Old names of manage apps.
    822             intentClass = com.android.settings.applications.ManageApplications.class.getName();
    823         }
    824 
    825         return intentClass;
    826     }
    827 
    828     /**
    829      * Start a new fragment containing a preference panel.  If the preferences
    830      * are being displayed in multi-pane mode, the given fragment class will
    831      * be instantiated and placed in the appropriate pane.  If running in
    832      * single-pane mode, a new activity will be launched in which to show the
    833      * fragment.
    834      *
    835      * @param fragmentClass Full name of the class implementing the fragment.
    836      * @param args Any desired arguments to supply to the fragment.
    837      * @param titleRes Optional resource identifier of the title of this
    838      * fragment.
    839      * @param titleText Optional text of the title of this fragment.
    840      * @param resultTo Optional fragment that result data should be sent to.
    841      * If non-null, resultTo.onActivityResult() will be called when this
    842      * preference panel is done.  The launched panel must use
    843      * {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
    844      * @param resultRequestCode If resultTo is non-null, this is the caller's
    845      * request code to be received with the result.
    846      */
    847     public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
    848             CharSequence titleText, Fragment resultTo, int resultRequestCode) {
    849         String title = null;
    850         if (titleRes < 0) {
    851             if (titleText != null) {
    852                 title = titleText.toString();
    853             } else {
    854                 // There not much we can do in that case
    855                 title = "";
    856             }
    857         }
    858         Utils.startWithFragment(this, fragmentClass, args, resultTo, resultRequestCode,
    859                 titleRes, title, mIsShortcut);
    860     }
    861 
    862     /**
    863      * Start a new fragment in a new activity containing a preference panel for a given user. If the
    864      * preferences are being displayed in multi-pane mode, the given fragment class will be
    865      * instantiated and placed in the appropriate pane. If running in single-pane mode, a new
    866      * activity will be launched in which to show the fragment.
    867      *
    868      * @param fragmentClass Full name of the class implementing the fragment.
    869      * @param args Any desired arguments to supply to the fragment.
    870      * @param titleRes Optional resource identifier of the title of this fragment.
    871      * @param titleText Optional text of the title of this fragment.
    872      * @param userHandle The user for which the panel has to be started.
    873      */
    874     public void startPreferencePanelAsUser(String fragmentClass, Bundle args, int titleRes,
    875             CharSequence titleText, UserHandle userHandle) {
    876         String title = null;
    877         if (titleRes < 0) {
    878             if (titleText != null) {
    879                 title = titleText.toString();
    880             } else {
    881                 // There not much we can do in that case
    882                 title = "";
    883             }
    884         }
    885         Utils.startWithFragmentAsUser(this, fragmentClass, args,
    886                 titleRes, title, mIsShortcut, userHandle);
    887     }
    888 
    889     /**
    890      * Called by a preference panel fragment to finish itself.
    891      *
    892      * @param caller The fragment that is asking to be finished.
    893      * @param resultCode Optional result code to send back to the original
    894      * launching fragment.
    895      * @param resultData Optional result data to send back to the original
    896      * launching fragment.
    897      */
    898     public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
    899         setResult(resultCode, resultData);
    900         finish();
    901     }
    902 
    903     /**
    904      * Start a new fragment.
    905      *
    906      * @param fragment The fragment to start
    907      * @param push If true, the current fragment will be pushed onto the back stack.  If false,
    908      * the current fragment will be replaced.
    909      */
    910     public void startPreferenceFragment(Fragment fragment, boolean push) {
    911         FragmentTransaction transaction = getFragmentManager().beginTransaction();
    912         transaction.replace(R.id.main_content, fragment);
    913         if (push) {
    914             transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    915             transaction.addToBackStack(BACK_STACK_PREFS);
    916         } else {
    917             transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    918         }
    919         transaction.commitAllowingStateLoss();
    920     }
    921 
    922     /**
    923      * Switch to a specific Fragment with taking care of validation, Title and BackStack
    924      */
    925     private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
    926             boolean addToBackStack, int titleResId, CharSequence title, boolean withTransition) {
    927         if (validate && !isValidFragment(fragmentName)) {
    928             throw new IllegalArgumentException("Invalid fragment for this activity: "
    929                     + fragmentName);
    930         }
    931         Fragment f = Fragment.instantiate(this, fragmentName, args);
    932         FragmentTransaction transaction = getFragmentManager().beginTransaction();
    933         transaction.replace(R.id.main_content, f);
    934         if (withTransition) {
    935             TransitionManager.beginDelayedTransition(mContent);
    936         }
    937         if (addToBackStack) {
    938             transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS);
    939         }
    940         if (titleResId > 0) {
    941             transaction.setBreadCrumbTitle(titleResId);
    942         } else if (title != null) {
    943             transaction.setBreadCrumbTitle(title);
    944         }
    945         transaction.commitAllowingStateLoss();
    946         getFragmentManager().executePendingTransactions();
    947         return f;
    948     }
    949 
    950     /**
    951      * Called when the activity needs its list of categories/tiles built.
    952      *
    953      * @param categories The list in which to place the tiles categories.
    954      */
    955     private void buildDashboardCategories(List<DashboardCategory> categories) {
    956         categories.clear();
    957         loadCategoriesFromResource(R.xml.dashboard_categories, categories);
    958         updateTilesList(categories);
    959     }
    960 
    961     /**
    962      * Parse the given XML file as a categories description, adding each
    963      * parsed categories and tiles into the target list.
    964      *
    965      * @param resid The XML resource to load and parse.
    966      * @param target The list in which the parsed categories and tiles should be placed.
    967      */
    968     private void loadCategoriesFromResource(int resid, List<DashboardCategory> target) {
    969         XmlResourceParser parser = null;
    970         try {
    971             parser = getResources().getXml(resid);
    972             AttributeSet attrs = Xml.asAttributeSet(parser);
    973 
    974             int type;
    975             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    976                     && type != XmlPullParser.START_TAG) {
    977                 // Parse next until start tag is found
    978             }
    979 
    980             String nodeName = parser.getName();
    981             if (!"dashboard-categories".equals(nodeName)) {
    982                 throw new RuntimeException(
    983                         "XML document must start with <preference-categories> tag; found"
    984                                 + nodeName + " at " + parser.getPositionDescription());
    985             }
    986 
    987             Bundle curBundle = null;
    988 
    989             final int outerDepth = parser.getDepth();
    990             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    991                     && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    992                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    993                     continue;
    994                 }
    995 
    996                 nodeName = parser.getName();
    997                 if ("dashboard-category".equals(nodeName)) {
    998                     DashboardCategory category = new DashboardCategory();
    999 
   1000                     TypedArray sa = obtainStyledAttributes(
   1001                             attrs, com.android.internal.R.styleable.PreferenceHeader);
   1002                     category.id = sa.getResourceId(
   1003                             com.android.internal.R.styleable.PreferenceHeader_id,
   1004                             (int)DashboardCategory.CAT_ID_UNDEFINED);
   1005 
   1006                     TypedValue tv = sa.peekValue(
   1007                             com.android.internal.R.styleable.PreferenceHeader_title);
   1008                     if (tv != null && tv.type == TypedValue.TYPE_STRING) {
   1009                         if (tv.resourceId != 0) {
   1010                             category.titleRes = tv.resourceId;
   1011                         } else {
   1012                             category.title = tv.string;
   1013                         }
   1014                     }
   1015                     sa.recycle();
   1016 
   1017                     final int innerDepth = parser.getDepth();
   1018                     while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   1019                             && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
   1020                         if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   1021                             continue;
   1022                         }
   1023 
   1024                         String innerNodeName = parser.getName();
   1025                         if (innerNodeName.equals("dashboard-tile")) {
   1026                             DashboardTile tile = new DashboardTile();
   1027 
   1028                             sa = obtainStyledAttributes(
   1029                                     attrs, com.android.internal.R.styleable.PreferenceHeader);
   1030                             tile.id = sa.getResourceId(
   1031                                     com.android.internal.R.styleable.PreferenceHeader_id,
   1032                                     (int)TILE_ID_UNDEFINED);
   1033                             tv = sa.peekValue(
   1034                                     com.android.internal.R.styleable.PreferenceHeader_title);
   1035                             if (tv != null && tv.type == TypedValue.TYPE_STRING) {
   1036                                 if (tv.resourceId != 0) {
   1037                                     tile.titleRes = tv.resourceId;
   1038                                 } else {
   1039                                     tile.title = tv.string;
   1040                                 }
   1041                             }
   1042                             tv = sa.peekValue(
   1043                                     com.android.internal.R.styleable.PreferenceHeader_summary);
   1044                             if (tv != null && tv.type == TypedValue.TYPE_STRING) {
   1045                                 if (tv.resourceId != 0) {
   1046                                     tile.summaryRes = tv.resourceId;
   1047                                 } else {
   1048                                     tile.summary = tv.string;
   1049                                 }
   1050                             }
   1051                             tile.iconRes = sa.getResourceId(
   1052                                     com.android.internal.R.styleable.PreferenceHeader_icon, 0);
   1053                             tile.fragment = sa.getString(
   1054                                     com.android.internal.R.styleable.PreferenceHeader_fragment);
   1055                             sa.recycle();
   1056 
   1057                             if (curBundle == null) {
   1058                                 curBundle = new Bundle();
   1059                             }
   1060 
   1061                             final int innerDepth2 = parser.getDepth();
   1062                             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
   1063                                     && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth2)) {
   1064                                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
   1065                                     continue;
   1066                                 }
   1067 
   1068                                 String innerNodeName2 = parser.getName();
   1069                                 if (innerNodeName2.equals("extra")) {
   1070                                     getResources().parseBundleExtra("extra", attrs, curBundle);
   1071                                     XmlUtils.skipCurrentTag(parser);
   1072 
   1073                                 } else if (innerNodeName2.equals("intent")) {
   1074                                     tile.intent = Intent.parseIntent(getResources(), parser, attrs);
   1075 
   1076                                 } else {
   1077                                     XmlUtils.skipCurrentTag(parser);
   1078                                 }
   1079                             }
   1080 
   1081                             if (curBundle.size() > 0) {
   1082                                 tile.fragmentArguments = curBundle;
   1083                                 curBundle = null;
   1084                             }
   1085 
   1086                             // Show the SIM Cards setting if there are more than 2 SIMs installed.
   1087                             if(tile.id != R.id.sim_settings || Utils.showSimCardTile(this)){
   1088                                 category.addTile(tile);
   1089                             }
   1090 
   1091                         } else {
   1092                             XmlUtils.skipCurrentTag(parser);
   1093                         }
   1094                     }
   1095 
   1096                     target.add(category);
   1097                 } else {
   1098                     XmlUtils.skipCurrentTag(parser);
   1099                 }
   1100             }
   1101 
   1102         } catch (XmlPullParserException e) {
   1103             throw new RuntimeException("Error parsing categories", e);
   1104         } catch (IOException e) {
   1105             throw new RuntimeException("Error parsing categories", e);
   1106         } finally {
   1107             if (parser != null) parser.close();
   1108         }
   1109     }
   1110 
   1111     private void updateTilesList(List<DashboardCategory> target) {
   1112         final boolean showDev = mDevelopmentPreferences.getBoolean(
   1113                 DevelopmentSettings.PREF_SHOW,
   1114                 android.os.Build.TYPE.equals("eng"));
   1115 
   1116         final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
   1117 
   1118         final int size = target.size();
   1119         for (int i = 0; i < size; i++) {
   1120 
   1121             DashboardCategory category = target.get(i);
   1122 
   1123             // Ids are integers, so downcasting is ok
   1124             int id = (int) category.id;
   1125             int n = category.getTilesCount() - 1;
   1126             while (n >= 0) {
   1127 
   1128                 DashboardTile tile = category.getTile(n);
   1129                 boolean removeTile = false;
   1130                 id = (int) tile.id;
   1131                 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
   1132                     if (!Utils.updateTileToSpecificActivityFromMetaDataOrRemove(this, tile)) {
   1133                         removeTile = true;
   1134                     }
   1135                 } else if (id == R.id.wifi_settings) {
   1136                     // Remove WiFi Settings if WiFi service is not available.
   1137                     if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
   1138                         removeTile = true;
   1139                     }
   1140                 } else if (id == R.id.bluetooth_settings) {
   1141                     // Remove Bluetooth Settings if Bluetooth service is not available.
   1142                     if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
   1143                         removeTile = true;
   1144                     }
   1145                 } else if (id == R.id.data_usage_settings) {
   1146                     // Remove data usage when kernel module not enabled
   1147                     final INetworkManagementService netManager = INetworkManagementService.Stub
   1148                             .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
   1149                     try {
   1150                         if (!netManager.isBandwidthControlEnabled()) {
   1151                             removeTile = true;
   1152                         }
   1153                     } catch (RemoteException e) {
   1154                         // ignored
   1155                     }
   1156                 } else if (id == R.id.battery_settings) {
   1157                     // Remove battery settings when battery is not available. (e.g. TV)
   1158 
   1159                     if (!mBatteryPresent) {
   1160                         removeTile = true;
   1161                     }
   1162                 } else if (id == R.id.home_settings) {
   1163                     if (!updateHomeSettingTiles(tile)) {
   1164                         removeTile = true;
   1165                     }
   1166                 } else if (id == R.id.user_settings) {
   1167                     boolean hasMultipleUsers =
   1168                             ((UserManager) getSystemService(Context.USER_SERVICE))
   1169                                     .getUserCount() > 1;
   1170                     if (!UserHandle.MU_ENABLED
   1171                             || (!UserManager.supportsMultipleUsers()
   1172                                     && !hasMultipleUsers)
   1173                             || Utils.isMonkeyRunning()) {
   1174                         removeTile = true;
   1175                     }
   1176                 } else if (id == R.id.nfc_payment_settings) {
   1177                     if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
   1178                         removeTile = true;
   1179                     } else {
   1180                         // Only show if NFC is on and we have the HCE feature
   1181                         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
   1182                         if (adapter == null || !adapter.isEnabled() ||
   1183                                 !getPackageManager().hasSystemFeature(
   1184                                         PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
   1185                             removeTile = true;
   1186                         }
   1187                     }
   1188                 } else if (id == R.id.print_settings) {
   1189                     boolean hasPrintingSupport = getPackageManager().hasSystemFeature(
   1190                             PackageManager.FEATURE_PRINTING);
   1191                     if (!hasPrintingSupport) {
   1192                         removeTile = true;
   1193                     }
   1194                 } else if (id == R.id.development_settings) {
   1195                     if (!showDev || um.hasUserRestriction(
   1196                             UserManager.DISALLOW_DEBUGGING_FEATURES)) {
   1197                         removeTile = true;
   1198                     }
   1199                 }
   1200 
   1201                 if (UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
   1202                         && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
   1203                     removeTile = true;
   1204                 }
   1205 
   1206                 if (removeTile && n < category.getTilesCount()) {
   1207                     category.removeTile(n);
   1208                 }
   1209                 n--;
   1210             }
   1211         }
   1212     }
   1213 
   1214     private boolean updateHomeSettingTiles(DashboardTile tile) {
   1215         // Once we decide to show Home settings, keep showing it forever
   1216         SharedPreferences sp = getSharedPreferences(HomeSettings.HOME_PREFS, Context.MODE_PRIVATE);
   1217         if (sp.getBoolean(HomeSettings.HOME_PREFS_DO_SHOW, false)) {
   1218             return true;
   1219         }
   1220 
   1221         try {
   1222             mHomeActivitiesCount = getHomeActivitiesCount();
   1223             if (mHomeActivitiesCount < 2) {
   1224                 // When there's only one available home app, omit this settings
   1225                 // category entirely at the top level UI.  If the user just
   1226                 // uninstalled the penultimate home app candidiate, we also
   1227                 // now tell them about why they aren't seeing 'Home' in the list.
   1228                 if (sShowNoHomeNotice) {
   1229                     sShowNoHomeNotice = false;
   1230                     NoHomeDialogFragment.show(this);
   1231                 }
   1232                 return false;
   1233             } else {
   1234                 // Okay, we're allowing the Home settings category.  Tell it, when
   1235                 // invoked via this front door, that we'll need to be told about the
   1236                 // case when the user uninstalls all but one home app.
   1237                 if (tile.fragmentArguments == null) {
   1238                     tile.fragmentArguments = new Bundle();
   1239                 }
   1240                 tile.fragmentArguments.putBoolean(HomeSettings.HOME_SHOW_NOTICE, true);
   1241             }
   1242         } catch (Exception e) {
   1243             // Can't look up the home activity; bail on configuring the icon
   1244             Log.w(LOG_TAG, "Problem looking up home activity!", e);
   1245         }
   1246 
   1247         sp.edit().putBoolean(HomeSettings.HOME_PREFS_DO_SHOW, true).apply();
   1248         return true;
   1249     }
   1250 
   1251     private void getMetaData() {
   1252         try {
   1253             ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
   1254                     PackageManager.GET_META_DATA);
   1255             if (ai == null || ai.metaData == null) return;
   1256             mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
   1257         } catch (NameNotFoundException nnfe) {
   1258             // No recovery
   1259             Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
   1260         }
   1261     }
   1262 
   1263     // give subclasses access to the Next button
   1264     public boolean hasNextButton() {
   1265         return mNextButton != null;
   1266     }
   1267 
   1268     public Button getNextButton() {
   1269         return mNextButton;
   1270     }
   1271 
   1272     @Override
   1273     public boolean shouldUpRecreateTask(Intent targetIntent) {
   1274         return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
   1275     }
   1276 
   1277     public static void requestHomeNotice() {
   1278         sShowNoHomeNotice = true;
   1279     }
   1280 
   1281     @Override
   1282     public boolean onQueryTextSubmit(String query) {
   1283         switchToSearchResultsFragmentIfNeeded();
   1284         mSearchQuery = query;
   1285         return mSearchResultsFragment.onQueryTextSubmit(query);
   1286     }
   1287 
   1288     @Override
   1289     public boolean onQueryTextChange(String newText) {
   1290         mSearchQuery = newText;
   1291         if (mSearchResultsFragment == null) {
   1292             return false;
   1293         }
   1294         return mSearchResultsFragment.onQueryTextChange(newText);
   1295     }
   1296 
   1297     @Override
   1298     public boolean onClose() {
   1299         return false;
   1300     }
   1301 
   1302     @Override
   1303     public boolean onMenuItemActionExpand(MenuItem item) {
   1304         if (item.getItemId() == mSearchMenuItem.getItemId()) {
   1305             switchToSearchResultsFragmentIfNeeded();
   1306         }
   1307         return true;
   1308     }
   1309 
   1310     @Override
   1311     public boolean onMenuItemActionCollapse(MenuItem item) {
   1312         if (item.getItemId() == mSearchMenuItem.getItemId()) {
   1313             if (mSearchMenuItemExpanded) {
   1314                 revertToInitialFragment();
   1315             }
   1316         }
   1317         return true;
   1318     }
   1319 
   1320     private void switchToSearchResultsFragmentIfNeeded() {
   1321         if (mSearchResultsFragment != null) {
   1322             return;
   1323         }
   1324         Fragment current = getFragmentManager().findFragmentById(R.id.main_content);
   1325         if (current != null && current instanceof SearchResultsSummary) {
   1326             mSearchResultsFragment = (SearchResultsSummary) current;
   1327         } else {
   1328             mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
   1329                     SearchResultsSummary.class.getName(), null, false, true,
   1330                     R.string.search_results_title, null, true);
   1331         }
   1332         mSearchResultsFragment.setSearchView(mSearchView);
   1333         mSearchMenuItemExpanded = true;
   1334     }
   1335 
   1336     public void needToRevertToInitialFragment() {
   1337         mNeedToRevertToInitialFragment = true;
   1338     }
   1339 
   1340     private void revertToInitialFragment() {
   1341         mNeedToRevertToInitialFragment = false;
   1342         mSearchResultsFragment = null;
   1343         mSearchMenuItemExpanded = false;
   1344         getFragmentManager().popBackStackImmediate(SettingsActivity.BACK_STACK_PREFS,
   1345                 FragmentManager.POP_BACK_STACK_INCLUSIVE);
   1346         if (mSearchMenuItem != null) {
   1347             mSearchMenuItem.collapseActionView();
   1348         }
   1349     }
   1350 
   1351     public Intent getResultIntentData() {
   1352         return mResultIntentData;
   1353     }
   1354 
   1355     public void setResultIntentData(Intent resultIntentData) {
   1356         mResultIntentData = resultIntentData;
   1357     }
   1358 }
   1359