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.Fragment;
     21 import android.app.FragmentManager;
     22 import android.app.FragmentTransaction;
     23 import android.content.BroadcastReceiver;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.content.SharedPreferences;
     29 import android.content.pm.ActivityInfo;
     30 import android.content.pm.PackageManager;
     31 import android.content.pm.PackageManager.NameNotFoundException;
     32 import android.content.res.Configuration;
     33 import android.nfc.NfcAdapter;
     34 import android.os.AsyncTask;
     35 import android.os.Bundle;
     36 import android.os.UserHandle;
     37 import android.os.UserManager;
     38 import android.support.v14.preference.PreferenceFragment;
     39 import android.support.v7.preference.Preference;
     40 import android.support.v7.preference.PreferenceManager;
     41 import android.text.TextUtils;
     42 import android.transition.TransitionManager;
     43 import android.util.Log;
     44 import android.view.Menu;
     45 import android.view.MenuInflater;
     46 import android.view.MenuItem;
     47 import android.view.View;
     48 import android.view.View.OnClickListener;
     49 import android.view.ViewGroup;
     50 import android.widget.Button;
     51 import android.widget.SearchView;
     52 
     53 import com.android.internal.util.ArrayUtils;
     54 import com.android.settings.Settings.WifiSettingsActivity;
     55 import com.android.settings.accessibility.AccessibilitySettings;
     56 import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
     57 import com.android.settings.accessibility.CaptionPropertiesFragment;
     58 import com.android.settings.accounts.AccountSettings;
     59 import com.android.settings.accounts.AccountSyncSettings;
     60 import com.android.settings.accounts.ChooseAccountActivity;
     61 import com.android.settings.accounts.ManagedProfileSettings;
     62 import com.android.settings.applications.AdvancedAppSettings;
     63 import com.android.settings.applications.DrawOverlayDetails;
     64 import com.android.settings.applications.InstalledAppDetails;
     65 import com.android.settings.applications.ManageApplications;
     66 import com.android.settings.applications.ManageAssist;
     67 import com.android.settings.applications.NotificationApps;
     68 import com.android.settings.applications.ProcessStatsSummary;
     69 import com.android.settings.applications.ProcessStatsUi;
     70 import com.android.settings.applications.UsageAccessDetails;
     71 import com.android.settings.applications.VrListenerSettings;
     72 import com.android.settings.applications.WriteSettingsDetails;
     73 import com.android.settings.bluetooth.BluetoothSettings;
     74 import com.android.settings.dashboard.DashboardContainerFragment;
     75 import com.android.settings.dashboard.SearchResultsSummary;
     76 import com.android.settings.datausage.DataUsageSummary;
     77 import com.android.settings.deviceinfo.ImeiInformation;
     78 import com.android.settings.deviceinfo.PrivateVolumeForget;
     79 import com.android.settings.deviceinfo.PrivateVolumeSettings;
     80 import com.android.settings.deviceinfo.PublicVolumeSettings;
     81 import com.android.settings.deviceinfo.SimStatus;
     82 import com.android.settings.deviceinfo.Status;
     83 import com.android.settings.deviceinfo.StorageSettings;
     84 import com.android.settings.display.NightDisplaySettings;
     85 import com.android.settings.fuelgauge.BatterySaverSettings;
     86 import com.android.settings.fuelgauge.PowerUsageDetail;
     87 import com.android.settings.fuelgauge.PowerUsageSummary;
     88 import com.android.settings.gestures.GestureSettings;
     89 import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
     90 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
     91 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
     92 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment2;
     93 import com.android.settings.inputmethod.PhysicalKeyboardFragment;
     94 import com.android.settings.inputmethod.SpellCheckersSettings;
     95 import com.android.settings.inputmethod.UserDictionaryList;
     96 import com.android.settings.localepicker.LocaleListEditor;
     97 import com.android.settings.location.LocationSettings;
     98 import com.android.settings.nfc.AndroidBeam;
     99 import com.android.settings.nfc.PaymentSettings;
    100 import com.android.settings.notification.AppNotificationSettings;
    101 import com.android.settings.notification.ConfigureNotificationSettings;
    102 import com.android.settings.notification.NotificationAccessSettings;
    103 import com.android.settings.notification.NotificationStation;
    104 import com.android.settings.notification.OtherSoundSettings;
    105 import com.android.settings.notification.SoundSettings;
    106 import com.android.settings.notification.ZenAccessSettings;
    107 import com.android.settings.notification.ZenModeAutomationSettings;
    108 import com.android.settings.notification.ZenModeEventRuleSettings;
    109 import com.android.settings.notification.ZenModePrioritySettings;
    110 import com.android.settings.notification.ZenModeScheduleRuleSettings;
    111 import com.android.settings.notification.ZenModeSettings;
    112 import com.android.settings.notification.ZenModeVisualInterruptionSettings;
    113 import com.android.settings.print.PrintJobSettingsFragment;
    114 import com.android.settings.print.PrintSettingsFragment;
    115 import com.android.settings.qstile.DevelopmentTiles;
    116 import com.android.settings.search.DynamicIndexableContentMonitor;
    117 import com.android.settings.search.Index;
    118 import com.android.settings.sim.SimSettings;
    119 import com.android.settings.tts.TextToSpeechSettings;
    120 import com.android.settings.users.UserSettings;
    121 import com.android.settings.vpn2.VpnSettings;
    122 import com.android.settings.wfd.WifiDisplaySettings;
    123 import com.android.settings.widget.SwitchBar;
    124 import com.android.settings.wifi.AdvancedWifiSettings;
    125 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
    126 import com.android.settings.wifi.WifiAPITest;
    127 import com.android.settings.wifi.WifiInfo;
    128 import com.android.settings.wifi.WifiSettings;
    129 import com.android.settings.wifi.p2p.WifiP2pSettings;
    130 import com.android.settingslib.drawer.DashboardCategory;
    131 import com.android.settingslib.drawer.SettingsDrawerActivity;
    132 import com.android.settingslib.drawer.Tile;
    133 
    134 import java.net.URISyntaxException;
    135 import java.util.ArrayList;
    136 import java.util.List;
    137 import java.util.Set;
    138 
    139 public class SettingsActivity extends SettingsDrawerActivity
    140         implements PreferenceManager.OnPreferenceTreeClickListener,
    141         PreferenceFragment.OnPreferenceStartFragmentCallback,
    142         ButtonBarHandler, FragmentManager.OnBackStackChangedListener,
    143         SearchView.OnQueryTextListener, SearchView.OnCloseListener,
    144         MenuItem.OnActionExpandListener {
    145 
    146     private static final String LOG_TAG = "Settings";
    147 
    148     private static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
    149 
    150     // Constants for state save/restore
    151     private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
    152     private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
    153     private static final String SAVE_KEY_SEARCH_QUERY = ":settings:search_query";
    154     private static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
    155     private static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search";
    156     private static final String SAVE_KEY_HOME_ACTIVITIES_COUNT = ":settings:home_activities_count";
    157 
    158     /**
    159      * When starting this activity, the invoking Intent can contain this extra
    160      * string to specify which fragment should be initially displayed.
    161      * <p/>Starting from Key Lime Pie, when this argument is passed in, the activity
    162      * will call isValidFragment() to confirm that the fragment class name is valid for this
    163      * activity.
    164      */
    165     public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
    166 
    167     /**
    168      * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
    169      * this extra can also be specified to supply a Bundle of arguments to pass
    170      * to that fragment when it is instantiated during the initial creation
    171      * of the activity.
    172      */
    173     public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
    174 
    175     /**
    176      * Fragment "key" argument passed thru {@link #EXTRA_SHOW_FRAGMENT_ARGUMENTS}
    177      */
    178     public static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
    179 
    180     public static final String BACK_STACK_PREFS = ":settings:prefs";
    181 
    182     // extras that allow any preference activity to be launched as part of a wizard
    183 
    184     // show Back and Next buttons? takes boolean parameter
    185     // Back will then return RESULT_CANCELED and Next RESULT_OK
    186     protected static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
    187 
    188     // add a Skip button?
    189     private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
    190 
    191     // specify custom text for the Back or Next buttons, or cause a button to not appear
    192     // at all by setting it to null
    193     protected static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
    194     protected static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
    195 
    196     /**
    197      * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
    198      * those extra can also be specify to supply the title or title res id to be shown for
    199      * that fragment.
    200      */
    201     public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
    202     /**
    203      * The package name used to resolve the title resource id.
    204      */
    205     public static final String EXTRA_SHOW_FRAGMENT_TITLE_RES_PACKAGE_NAME =
    206             ":settings:show_fragment_title_res_package_name";
    207     public static final String EXTRA_SHOW_FRAGMENT_TITLE_RESID =
    208             ":settings:show_fragment_title_resid";
    209     public static final String EXTRA_SHOW_FRAGMENT_AS_SHORTCUT =
    210             ":settings:show_fragment_as_shortcut";
    211 
    212     public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
    213             ":settings:show_fragment_as_subsetting";
    214 
    215     public static final String EXTRA_HIDE_DRAWER = ":settings:hide_drawer";
    216 
    217     public static final String META_DATA_KEY_FRAGMENT_CLASS =
    218         "com.android.settings.FRAGMENT_CLASS";
    219 
    220     private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
    221 
    222     private static final String EMPTY_QUERY = "";
    223 
    224     private static final int REQUEST_SUGGESTION = 42;
    225 
    226     private String mFragmentClass;
    227 
    228     private CharSequence mInitialTitle;
    229     private int mInitialTitleResId;
    230 
    231     // Show only these settings for restricted users
    232     private String[] SETTINGS_FOR_RESTRICTED = {
    233             //wireless_section
    234             WifiSettingsActivity.class.getName(),
    235             Settings.BluetoothSettingsActivity.class.getName(),
    236             Settings.DataUsageSummaryActivity.class.getName(),
    237             Settings.SimSettingsActivity.class.getName(),
    238             Settings.WirelessSettingsActivity.class.getName(),
    239             //device_section
    240             Settings.HomeSettingsActivity.class.getName(),
    241             Settings.SoundSettingsActivity.class.getName(),
    242             Settings.DisplaySettingsActivity.class.getName(),
    243             Settings.StorageSettingsActivity.class.getName(),
    244             Settings.ManageApplicationsActivity.class.getName(),
    245             Settings.PowerUsageSummaryActivity.class.getName(),
    246             Settings.GestureSettingsActivity.class.getName(),
    247             //personal_section
    248             Settings.LocationSettingsActivity.class.getName(),
    249             Settings.SecuritySettingsActivity.class.getName(),
    250             Settings.InputMethodAndLanguageSettingsActivity.class.getName(),
    251             Settings.UserSettingsActivity.class.getName(),
    252             Settings.AccountSettingsActivity.class.getName(),
    253             //system_section
    254             Settings.DateTimeSettingsActivity.class.getName(),
    255             Settings.DeviceInfoSettingsActivity.class.getName(),
    256             Settings.AccessibilitySettingsActivity.class.getName(),
    257             Settings.PrintSettingsActivity.class.getName(),
    258             Settings.PaymentSettingsActivity.class.getName(),
    259     };
    260 
    261     private static final String[] ENTRY_FRAGMENTS = {
    262             WirelessSettings.class.getName(),
    263             WifiSettings.class.getName(),
    264             AdvancedWifiSettings.class.getName(),
    265             SavedAccessPointsWifiSettings.class.getName(),
    266             BluetoothSettings.class.getName(),
    267             SimSettings.class.getName(),
    268             TetherSettings.class.getName(),
    269             WifiP2pSettings.class.getName(),
    270             VpnSettings.class.getName(),
    271             DateTimeSettings.class.getName(),
    272             LocaleListEditor.class.getName(),
    273             InputMethodAndLanguageSettings.class.getName(),
    274             AvailableVirtualKeyboardFragment.class.getName(),
    275             SpellCheckersSettings.class.getName(),
    276             UserDictionaryList.class.getName(),
    277             UserDictionarySettings.class.getName(),
    278             HomeSettings.class.getName(),
    279             DisplaySettings.class.getName(),
    280             DeviceInfoSettings.class.getName(),
    281             ManageApplications.class.getName(),
    282             NotificationApps.class.getName(),
    283             ManageAssist.class.getName(),
    284             ProcessStatsUi.class.getName(),
    285             NotificationStation.class.getName(),
    286             LocationSettings.class.getName(),
    287             SecuritySettings.class.getName(),
    288             UsageAccessDetails.class.getName(),
    289             PrivacySettings.class.getName(),
    290             DeviceAdminSettings.class.getName(),
    291             AccessibilitySettings.class.getName(),
    292             AccessibilitySettingsForSetupWizard.class.getName(),
    293             CaptionPropertiesFragment.class.getName(),
    294             com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment.class.getName(),
    295             TextToSpeechSettings.class.getName(),
    296             StorageSettings.class.getName(),
    297             PrivateVolumeForget.class.getName(),
    298             PrivateVolumeSettings.class.getName(),
    299             PublicVolumeSettings.class.getName(),
    300             DevelopmentSettings.class.getName(),
    301             AndroidBeam.class.getName(),
    302             WifiDisplaySettings.class.getName(),
    303             PowerUsageSummary.class.getName(),
    304             AccountSyncSettings.class.getName(),
    305             AccountSettings.class.getName(),
    306             GestureSettings.class.getName(),
    307             CryptKeeperSettings.class.getName(),
    308             DataUsageSummary.class.getName(),
    309             DreamSettings.class.getName(),
    310             UserSettings.class.getName(),
    311             NotificationAccessSettings.class.getName(),
    312             ZenAccessSettings.class.getName(),
    313             PrintSettingsFragment.class.getName(),
    314             PrintJobSettingsFragment.class.getName(),
    315             TrustedCredentialsSettings.class.getName(),
    316             PaymentSettings.class.getName(),
    317             KeyboardLayoutPickerFragment.class.getName(),
    318             KeyboardLayoutPickerFragment2.class.getName(),
    319             PhysicalKeyboardFragment.class.getName(),
    320             ZenModeSettings.class.getName(),
    321             SoundSettings.class.getName(),
    322             ConfigureNotificationSettings.class.getName(),
    323             ChooseLockPassword.ChooseLockPasswordFragment.class.getName(),
    324             ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
    325             InstalledAppDetails.class.getName(),
    326             BatterySaverSettings.class.getName(),
    327             AppNotificationSettings.class.getName(),
    328             OtherSoundSettings.class.getName(),
    329             ApnSettings.class.getName(),
    330             ApnEditor.class.getName(),
    331             WifiCallingSettings.class.getName(),
    332             ZenModePrioritySettings.class.getName(),
    333             ZenModeAutomationSettings.class.getName(),
    334             ZenModeScheduleRuleSettings.class.getName(),
    335             ZenModeEventRuleSettings.class.getName(),
    336             ZenModeVisualInterruptionSettings.class.getName(),
    337             ProcessStatsUi.class.getName(),
    338             PowerUsageDetail.class.getName(),
    339             ProcessStatsSummary.class.getName(),
    340             DrawOverlayDetails.class.getName(),
    341             WriteSettingsDetails.class.getName(),
    342             AdvancedAppSettings.class.getName(),
    343             WallpaperTypeSettings.class.getName(),
    344             VrListenerSettings.class.getName(),
    345             ManagedProfileSettings.class.getName(),
    346             ChooseAccountActivity.class.getName(),
    347             IccLockSettings.class.getName(),
    348             ImeiInformation.class.getName(),
    349             SimStatus.class.getName(),
    350             Status.class.getName(),
    351             TestingSettings.class.getName(),
    352             WifiAPITest.class.getName(),
    353             WifiInfo.class.getName(),
    354             MasterClear.class.getName(),
    355             NightDisplaySettings.class.getName(),
    356     };
    357 
    358 
    359     private static final String[] LIKE_SHORTCUT_INTENT_ACTION_ARRAY = {
    360             "android.settings.APPLICATION_DETAILS_SETTINGS"
    361     };
    362 
    363     private SharedPreferences mDevelopmentPreferences;
    364     private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
    365 
    366     private boolean mBatteryPresent = true;
    367     private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
    368         @Override
    369         public void onReceive(Context context, Intent intent) {
    370             String action = intent.getAction();
    371             if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
    372                 boolean batteryPresent = Utils.isBatteryPresent(intent);
    373 
    374                 if (mBatteryPresent != batteryPresent) {
    375                     mBatteryPresent = batteryPresent;
    376                     updateTilesList();
    377                 }
    378             }
    379         }
    380     };
    381 
    382     private final BroadcastReceiver mUserAddRemoveReceiver = new BroadcastReceiver() {
    383         @Override
    384         public void onReceive(Context context, Intent intent) {
    385             String action = intent.getAction();
    386             if (action.equals(Intent.ACTION_USER_ADDED)
    387                     || action.equals(Intent.ACTION_USER_REMOVED)) {
    388                 Index.getInstance(getApplicationContext()).update();
    389             }
    390         }
    391     };
    392 
    393     private final DynamicIndexableContentMonitor mDynamicIndexableContentMonitor =
    394             new DynamicIndexableContentMonitor();
    395 
    396     private ActionBar mActionBar;
    397     private SwitchBar mSwitchBar;
    398 
    399     private Button mNextButton;
    400 
    401     private boolean mDisplayHomeAsUpEnabled;
    402     private boolean mDisplaySearch;
    403 
    404     private boolean mIsShowingDashboard;
    405     private boolean mIsShortcut;
    406 
    407     private ViewGroup mContent;
    408 
    409     private SearchView mSearchView;
    410     private MenuItem mSearchMenuItem;
    411     private boolean mSearchMenuItemExpanded = false;
    412     private SearchResultsSummary mSearchResultsFragment;
    413     private String mSearchQuery;
    414 
    415     // Categories
    416     private ArrayList<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
    417 
    418     private static final String MSG_DATA_FORCE_REFRESH = "msg_data_force_refresh";
    419 
    420     private boolean mNeedToRevertToInitialFragment = false;
    421 
    422     private Intent mResultIntentData;
    423     private ComponentName mCurrentSuggestion;
    424 
    425     public SwitchBar getSwitchBar() {
    426         return mSwitchBar;
    427     }
    428 
    429     @Override
    430     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
    431         startPreferencePanel(pref.getFragment(), pref.getExtras(), -1, pref.getTitle(),
    432                 null, 0);
    433         return true;
    434     }
    435 
    436     @Override
    437     public boolean onPreferenceTreeClick(Preference preference) {
    438         return false;
    439     }
    440 
    441     @Override
    442     public void onConfigurationChanged(Configuration newConfig) {
    443         super.onConfigurationChanged(newConfig);
    444         Index.getInstance(this).update();
    445     }
    446 
    447     @Override
    448     public boolean onCreateOptionsMenu(Menu menu) {
    449         if (!mDisplaySearch) {
    450             return false;
    451         }
    452 
    453         MenuInflater inflater = getMenuInflater();
    454         inflater.inflate(R.menu.options_menu, menu);
    455 
    456         // Cache the search query (can be overriden by the OnQueryTextListener)
    457         final String query = mSearchQuery;
    458 
    459         mSearchMenuItem = menu.findItem(R.id.search);
    460         mSearchView = (SearchView) mSearchMenuItem.getActionView();
    461 
    462         if (mSearchMenuItem == null || mSearchView == null) {
    463             return false;
    464         }
    465 
    466         if (mSearchResultsFragment != null) {
    467             mSearchResultsFragment.setSearchView(mSearchView);
    468         }
    469 
    470         mSearchMenuItem.setOnActionExpandListener(this);
    471         mSearchView.setOnQueryTextListener(this);
    472         mSearchView.setOnCloseListener(this);
    473 
    474         if (mSearchMenuItemExpanded) {
    475             mSearchMenuItem.expandActionView();
    476         }
    477         mSearchView.setQuery(query, true /* submit */);
    478 
    479         return true;
    480     }
    481 
    482     @Override
    483     public SharedPreferences getSharedPreferences(String name, int mode) {
    484         if (name.equals(getPackageName() + "_preferences")) {
    485             return new SharedPreferencesLogger(this, getMetricsTag());
    486         }
    487         return super.getSharedPreferences(name, mode);
    488     }
    489 
    490     private String getMetricsTag() {
    491         String tag = getClass().getName();
    492         if (getIntent() != null && getIntent().hasExtra(EXTRA_SHOW_FRAGMENT)) {
    493             tag = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
    494         }
    495         if (tag.startsWith("com.android.settings.")) {
    496             tag = tag.replace("com.android.settings.", "");
    497         }
    498         return tag;
    499     }
    500 
    501     private static boolean isShortCutIntent(final Intent intent) {
    502         Set<String> categories = intent.getCategories();
    503         return (categories != null) && categories.contains("com.android.settings.SHORTCUT");
    504     }
    505 
    506     private static boolean isLikeShortCutIntent(final Intent intent) {
    507         String action = intent.getAction();
    508         if (action == null) {
    509             return false;
    510         }
    511         for (int i = 0; i < LIKE_SHORTCUT_INTENT_ACTION_ARRAY.length; i++) {
    512             if (LIKE_SHORTCUT_INTENT_ACTION_ARRAY[i].equals(action)) return true;
    513         }
    514         return false;
    515     }
    516 
    517     @Override
    518     protected void onCreate(Bundle savedState) {
    519         super.onCreate(savedState);
    520         long startTime = System.currentTimeMillis();
    521 
    522         // Should happen before any call to getIntent()
    523         getMetaData();
    524 
    525         final Intent intent = getIntent();
    526         if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
    527             getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
    528         }
    529         if (intent.getBooleanExtra(EXTRA_HIDE_DRAWER, false)) {
    530             setIsDrawerPresent(false);
    531         }
    532 
    533         mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
    534                 Context.MODE_PRIVATE);
    535 
    536         // Getting Intent properties can only be done after the super.onCreate(...)
    537         final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
    538 
    539         mIsShortcut = isShortCutIntent(intent) || isLikeShortCutIntent(intent) ||
    540                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, false);
    541 
    542         final ComponentName cn = intent.getComponent();
    543         final String className = cn.getClassName();
    544 
    545         mIsShowingDashboard = className.equals(Settings.class.getName())
    546                 || className.equals(Settings.WirelessSettings.class.getName())
    547                 || className.equals(Settings.DeviceSettings.class.getName())
    548                 || className.equals(Settings.PersonalSettings.class.getName())
    549                 || className.equals(Settings.WirelessSettings.class.getName());
    550 
    551         // This is a "Sub Settings" when:
    552         // - this is a real SubSettings
    553         // - or :settings:show_fragment_as_subsetting is passed to the Intent
    554         final boolean isSubSettings = this instanceof SubSettings ||
    555                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
    556 
    557         // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content insets
    558         if (isSubSettings) {
    559             // Check also that we are not a Theme Dialog as we don't want to override them
    560             final int themeResId = getThemeResId();
    561             if (themeResId != R.style.Theme_DialogWhenLarge &&
    562                     themeResId != R.style.Theme_SubSettingsDialogWhenLarge) {
    563                 setTheme(R.style.Theme_SubSettings);
    564             }
    565         }
    566 
    567         setContentView(mIsShowingDashboard ?
    568                 R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
    569 
    570         mContent = (ViewGroup) findViewById(R.id.main_content);
    571 
    572         getFragmentManager().addOnBackStackChangedListener(this);
    573 
    574         if (mIsShowingDashboard) {
    575             // Run the Index update only if we have some space
    576             if (!Utils.isLowStorage(this)) {
    577                 long indexStartTime = System.currentTimeMillis();
    578                 Index.getInstance(getApplicationContext()).update();
    579                 if (DEBUG_TIMING) Log.d(LOG_TAG, "Index.update() took "
    580                         + (System.currentTimeMillis() - indexStartTime) + " ms");
    581             } else {
    582                 Log.w(LOG_TAG, "Cannot update the Indexer as we are running low on storage space!");
    583             }
    584         }
    585 
    586         if (savedState != null) {
    587             // We are restarting from a previous saved state; used that to initialize, instead
    588             // of starting fresh.
    589             mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
    590             mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
    591 
    592             setTitleFromIntent(intent);
    593 
    594             ArrayList<DashboardCategory> categories =
    595                     savedState.getParcelableArrayList(SAVE_KEY_CATEGORIES);
    596             if (categories != null) {
    597                 mCategories.clear();
    598                 mCategories.addAll(categories);
    599                 setTitleFromBackStack();
    600             }
    601 
    602             mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
    603             mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
    604         } else {
    605             if (!mIsShowingDashboard) {
    606                 mDisplaySearch = false;
    607                 // UP will be shown only if it is a sub settings
    608                 if (mIsShortcut) {
    609                     mDisplayHomeAsUpEnabled = isSubSettings;
    610                 } else if (isSubSettings) {
    611                     mDisplayHomeAsUpEnabled = true;
    612                 } else {
    613                     mDisplayHomeAsUpEnabled = false;
    614                 }
    615                 setTitleFromIntent(intent);
    616 
    617                 Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
    618                 switchToFragment(initialFragmentName, initialArguments, true, false,
    619                         mInitialTitleResId, mInitialTitle, false);
    620             } else {
    621                 // No UP affordance if we are displaying the main Dashboard
    622                 mDisplayHomeAsUpEnabled = false;
    623                 // Show Search affordance
    624                 mDisplaySearch = true;
    625                 mInitialTitleResId = R.string.dashboard_title;
    626                 switchToFragment(DashboardContainerFragment.class.getName(), null, false, false,
    627                         mInitialTitleResId, mInitialTitle, false);
    628             }
    629         }
    630 
    631         mActionBar = getActionBar();
    632         if (mActionBar != null) {
    633             mActionBar.setDisplayHomeAsUpEnabled(mDisplayHomeAsUpEnabled);
    634             mActionBar.setHomeButtonEnabled(mDisplayHomeAsUpEnabled);
    635         }
    636         mSwitchBar = (SwitchBar) findViewById(R.id.switch_bar);
    637         if (mSwitchBar != null) {
    638             mSwitchBar.setMetricsTag(getMetricsTag());
    639         }
    640 
    641         // see if we should show Back/Next buttons
    642         if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
    643 
    644             View buttonBar = findViewById(R.id.button_bar);
    645             if (buttonBar != null) {
    646                 buttonBar.setVisibility(View.VISIBLE);
    647 
    648                 Button backButton = (Button)findViewById(R.id.back_button);
    649                 backButton.setOnClickListener(new OnClickListener() {
    650                     public void onClick(View v) {
    651                         setResult(RESULT_CANCELED, getResultIntentData());
    652                         finish();
    653                     }
    654                 });
    655                 Button skipButton = (Button)findViewById(R.id.skip_button);
    656                 skipButton.setOnClickListener(new OnClickListener() {
    657                     public void onClick(View v) {
    658                         setResult(RESULT_OK, getResultIntentData());
    659                         finish();
    660                     }
    661                 });
    662                 mNextButton = (Button)findViewById(R.id.next_button);
    663                 mNextButton.setOnClickListener(new OnClickListener() {
    664                     public void onClick(View v) {
    665                         setResult(RESULT_OK, getResultIntentData());
    666                         finish();
    667                     }
    668                 });
    669 
    670                 // set our various button parameters
    671                 if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
    672                     String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
    673                     if (TextUtils.isEmpty(buttonText)) {
    674                         mNextButton.setVisibility(View.GONE);
    675                     }
    676                     else {
    677                         mNextButton.setText(buttonText);
    678                     }
    679                 }
    680                 if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
    681                     String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
    682                     if (TextUtils.isEmpty(buttonText)) {
    683                         backButton.setVisibility(View.GONE);
    684                     }
    685                     else {
    686                         backButton.setText(buttonText);
    687                     }
    688                 }
    689                 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
    690                     skipButton.setVisibility(View.VISIBLE);
    691                 }
    692             }
    693         }
    694 
    695         if (DEBUG_TIMING) Log.d(LOG_TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
    696                 + " ms");
    697     }
    698 
    699     public void setDisplaySearchMenu(boolean displaySearch) {
    700         if (displaySearch != mDisplaySearch) {
    701             mDisplaySearch = displaySearch;
    702             invalidateOptionsMenu();
    703         }
    704     }
    705 
    706     private void setTitleFromIntent(Intent intent) {
    707         final int initialTitleResId = intent.getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
    708         if (initialTitleResId > 0) {
    709             mInitialTitle = null;
    710             mInitialTitleResId = initialTitleResId;
    711 
    712             final String initialTitleResPackageName = intent.getStringExtra(
    713                     EXTRA_SHOW_FRAGMENT_TITLE_RES_PACKAGE_NAME);
    714             if (initialTitleResPackageName != null) {
    715                 try {
    716                     Context authContext = createPackageContextAsUser(initialTitleResPackageName,
    717                             0 /* flags */, new UserHandle(UserHandle.myUserId()));
    718                     mInitialTitle = authContext.getResources().getText(mInitialTitleResId);
    719                     setTitle(mInitialTitle);
    720                     mInitialTitleResId = -1;
    721                     return;
    722                 } catch (NameNotFoundException e) {
    723                     Log.w(LOG_TAG, "Could not find package" + initialTitleResPackageName);
    724                 }
    725             } else {
    726                 setTitle(mInitialTitleResId);
    727             }
    728         } else {
    729             mInitialTitleResId = -1;
    730             final String initialTitle = intent.getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE);
    731             mInitialTitle = (initialTitle != null) ? initialTitle : getTitle();
    732             setTitle(mInitialTitle);
    733         }
    734     }
    735 
    736     @Override
    737     public void onBackStackChanged() {
    738         setTitleFromBackStack();
    739     }
    740 
    741     private void setTitleFromBackStack() {
    742         final int count = getFragmentManager().getBackStackEntryCount();
    743 
    744         if (count == 0) {
    745             if (mInitialTitleResId > 0) {
    746                 setTitle(mInitialTitleResId);
    747             } else {
    748                 setTitle(mInitialTitle);
    749             }
    750             return;
    751         }
    752 
    753         FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
    754         setTitleFromBackStackEntry(bse);
    755     }
    756 
    757     private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) {
    758         final CharSequence title;
    759         final int titleRes = bse.getBreadCrumbTitleRes();
    760         if (titleRes > 0) {
    761             title = getText(titleRes);
    762         } else {
    763             title = bse.getBreadCrumbTitle();
    764         }
    765         if (title != null) {
    766             setTitle(title);
    767         }
    768     }
    769 
    770     @Override
    771     protected void onSaveInstanceState(Bundle outState) {
    772         super.onSaveInstanceState(outState);
    773 
    774         if (mCategories.size() > 0) {
    775             outState.putParcelableArrayList(SAVE_KEY_CATEGORIES, mCategories);
    776         }
    777 
    778         outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled);
    779         outState.putBoolean(SAVE_KEY_SHOW_SEARCH, mDisplaySearch);
    780 
    781         if (mDisplaySearch) {
    782             // The option menus are created if the ActionBar is visible and they are also created
    783             // asynchronously. If you launch Settings with an Intent action like
    784             // android.intent.action.POWER_USAGE_SUMMARY and at the same time your device is locked
    785             // thru a LockScreen, onCreateOptionsMenu() is not yet called and references to the search
    786             // menu item and search view are null.
    787             boolean isExpanded = (mSearchMenuItem != null) && mSearchMenuItem.isActionViewExpanded();
    788             outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, isExpanded);
    789 
    790             String query = (mSearchView != null) ? mSearchView.getQuery().toString() : EMPTY_QUERY;
    791             outState.putString(SAVE_KEY_SEARCH_QUERY, query);
    792         }
    793     }
    794 
    795     @Override
    796     protected void onStart() {
    797         super.onStart();
    798 
    799         if (mNeedToRevertToInitialFragment) {
    800             revertToInitialFragment();
    801         }
    802 
    803         mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
    804             @Override
    805             public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    806                 updateTilesList();
    807             }
    808         };
    809         mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
    810                 mDevelopmentPreferencesListener);
    811 
    812         registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    813         registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_ADDED));
    814         registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
    815 
    816         mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
    817 
    818         if(mDisplaySearch && !TextUtils.isEmpty(mSearchQuery)) {
    819             onQueryTextSubmit(mSearchQuery);
    820         }
    821         updateTilesList();
    822     }
    823 
    824     @Override
    825     protected void onStop() {
    826         super.onStop();
    827         unregisterReceiver(mBatteryInfoReceiver);
    828         unregisterReceiver(mUserAddRemoveReceiver);
    829         mDynamicIndexableContentMonitor.unregister();
    830     }
    831 
    832     @Override
    833     public void onDestroy() {
    834         super.onDestroy();
    835 
    836         mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
    837                 mDevelopmentPreferencesListener);
    838         mDevelopmentPreferencesListener = null;
    839     }
    840 
    841     protected boolean isValidFragment(String fragmentName) {
    842         // Almost all fragments are wrapped in this,
    843         // except for a few that have their own activities.
    844         for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
    845             if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
    846         }
    847         return false;
    848     }
    849 
    850     @Override
    851     public Intent getIntent() {
    852         Intent superIntent = super.getIntent();
    853         String startingFragment = getStartingFragmentClass(superIntent);
    854         // This is called from super.onCreate, isMultiPane() is not yet reliable
    855         // Do not use onIsHidingHeaders either, which relies itself on this method
    856         if (startingFragment != null) {
    857             Intent modIntent = new Intent(superIntent);
    858             modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
    859             Bundle args = superIntent.getExtras();
    860             if (args != null) {
    861                 args = new Bundle(args);
    862             } else {
    863                 args = new Bundle();
    864             }
    865             args.putParcelable("intent", superIntent);
    866             modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
    867             return modIntent;
    868         }
    869         return superIntent;
    870     }
    871 
    872     /**
    873      * Checks if the component name in the intent is different from the Settings class and
    874      * returns the class name to load as a fragment.
    875      */
    876     private String getStartingFragmentClass(Intent intent) {
    877         if (mFragmentClass != null) return mFragmentClass;
    878 
    879         String intentClass = intent.getComponent().getClassName();
    880         if (intentClass.equals(getClass().getName())) return null;
    881 
    882         if ("com.android.settings.ManageApplications".equals(intentClass)
    883                 || "com.android.settings.RunningServices".equals(intentClass)
    884                 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
    885             // Old names of manage apps.
    886             intentClass = com.android.settings.applications.ManageApplications.class.getName();
    887         }
    888 
    889         return intentClass;
    890     }
    891 
    892     /**
    893      * Start a new fragment containing a preference panel.  If the preferences
    894      * are being displayed in multi-pane mode, the given fragment class will
    895      * be instantiated and placed in the appropriate pane.  If running in
    896      * single-pane mode, a new activity will be launched in which to show the
    897      * fragment.
    898      *
    899      * @param fragmentClass Full name of the class implementing the fragment.
    900      * @param args Any desired arguments to supply to the fragment.
    901      * @param titleRes Optional resource identifier of the title of this
    902      * fragment.
    903      * @param titleText Optional text of the title of this fragment.
    904      * @param resultTo Optional fragment that result data should be sent to.
    905      * If non-null, resultTo.onActivityResult() will be called when this
    906      * preference panel is done.  The launched panel must use
    907      * {@link #finishPreferencePanel(Fragment, int, Intent)} when done.
    908      * @param resultRequestCode If resultTo is non-null, this is the caller's
    909      * request code to be received with the result.
    910      */
    911     public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
    912             CharSequence titleText, Fragment resultTo, int resultRequestCode) {
    913         String title = null;
    914         if (titleRes < 0) {
    915             if (titleText != null) {
    916                 title = titleText.toString();
    917             } else {
    918                 // There not much we can do in that case
    919                 title = "";
    920             }
    921         }
    922         Utils.startWithFragment(this, fragmentClass, args, resultTo, resultRequestCode,
    923                 titleRes, title, mIsShortcut);
    924     }
    925 
    926     /**
    927      * Start a new fragment in a new activity containing a preference panel for a given user. If the
    928      * preferences are being displayed in multi-pane mode, the given fragment class will be
    929      * instantiated and placed in the appropriate pane. If running in single-pane mode, a new
    930      * activity will be launched in which to show the fragment.
    931      *
    932      * @param fragmentClass Full name of the class implementing the fragment.
    933      * @param args Any desired arguments to supply to the fragment.
    934      * @param titleRes Optional resource identifier of the title of this fragment.
    935      * @param titleText Optional text of the title of this fragment.
    936      * @param userHandle The user for which the panel has to be started.
    937      */
    938     public void startPreferencePanelAsUser(String fragmentClass, Bundle args, int titleRes,
    939             CharSequence titleText, UserHandle userHandle) {
    940         // This is a workaround.
    941         //
    942         // Calling startWithFragmentAsUser() without specifying FLAG_ACTIVITY_NEW_TASK to the intent
    943         // starting the fragment could cause a native stack corruption. See b/17523189. However,
    944         // adding that flag and start the preference panel with the same UserHandler will make it
    945         // impossible to use back button to return to the previous screen. See b/20042570.
    946         //
    947         // We work around this issue by adding FLAG_ACTIVITY_NEW_TASK to the intent, while doing
    948         // another check here to call startPreferencePanel() instead of startWithFragmentAsUser()
    949         // when we're calling it as the same user.
    950         if (userHandle.getIdentifier() == UserHandle.myUserId()) {
    951             startPreferencePanel(fragmentClass, args, titleRes, titleText, null, 0);
    952         } else {
    953             String title = null;
    954             if (titleRes < 0) {
    955                 if (titleText != null) {
    956                     title = titleText.toString();
    957                 } else {
    958                     // There not much we can do in that case
    959                     title = "";
    960                 }
    961             }
    962             Utils.startWithFragmentAsUser(this, fragmentClass, args,
    963                     titleRes, title, mIsShortcut, userHandle);
    964         }
    965     }
    966 
    967     /**
    968      * Called by a preference panel fragment to finish itself.
    969      *
    970      * @param caller The fragment that is asking to be finished.
    971      * @param resultCode Optional result code to send back to the original
    972      * launching fragment.
    973      * @param resultData Optional result data to send back to the original
    974      * launching fragment.
    975      */
    976     public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
    977         setResult(resultCode, resultData);
    978         finish();
    979     }
    980 
    981     /**
    982      * Start a new fragment.
    983      *
    984      * @param fragment The fragment to start
    985      * @param push If true, the current fragment will be pushed onto the back stack.  If false,
    986      * the current fragment will be replaced.
    987      */
    988     public void startPreferenceFragment(Fragment fragment, boolean push) {
    989         FragmentTransaction transaction = getFragmentManager().beginTransaction();
    990         transaction.replace(R.id.main_content, fragment);
    991         if (push) {
    992             transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    993             transaction.addToBackStack(BACK_STACK_PREFS);
    994         } else {
    995             transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    996         }
    997         transaction.commitAllowingStateLoss();
    998     }
    999 
   1000     /**
   1001      * Switch to a specific Fragment with taking care of validation, Title and BackStack
   1002      */
   1003     private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
   1004             boolean addToBackStack, int titleResId, CharSequence title, boolean withTransition) {
   1005         if (validate && !isValidFragment(fragmentName)) {
   1006             throw new IllegalArgumentException("Invalid fragment for this activity: "
   1007                     + fragmentName);
   1008         }
   1009         Fragment f = Fragment.instantiate(this, fragmentName, args);
   1010         FragmentTransaction transaction = getFragmentManager().beginTransaction();
   1011         transaction.replace(R.id.main_content, f);
   1012         if (withTransition) {
   1013             TransitionManager.beginDelayedTransition(mContent);
   1014         }
   1015         if (addToBackStack) {
   1016             transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS);
   1017         }
   1018         if (titleResId > 0) {
   1019             transaction.setBreadCrumbTitle(titleResId);
   1020         } else if (title != null) {
   1021             transaction.setBreadCrumbTitle(title);
   1022         }
   1023         transaction.commitAllowingStateLoss();
   1024         getFragmentManager().executePendingTransactions();
   1025         return f;
   1026     }
   1027 
   1028     private void updateTilesList() {
   1029         // Generally the items that are will be changing from these updates will
   1030         // not be in the top list of tiles, so run it in the background and the
   1031         // SettingsDrawerActivity will pick up on the updates automatically.
   1032         AsyncTask.execute(new Runnable() {
   1033             @Override
   1034             public void run() {
   1035                 doUpdateTilesList();
   1036             }
   1037         });
   1038     }
   1039 
   1040     private void doUpdateTilesList() {
   1041         PackageManager pm = getPackageManager();
   1042         final UserManager um = UserManager.get(this);
   1043         final boolean isAdmin = um.isAdminUser();
   1044 
   1045         String packageName = getPackageName();
   1046         setTileEnabled(new ComponentName(packageName, WifiSettingsActivity.class.getName()),
   1047                 pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin, pm);
   1048 
   1049         setTileEnabled(new ComponentName(packageName,
   1050                 Settings.BluetoothSettingsActivity.class.getName()),
   1051                 pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin, pm);
   1052 
   1053         setTileEnabled(new ComponentName(packageName,
   1054                 Settings.DataUsageSummaryActivity.class.getName()),
   1055                 Utils.isBandwidthControlEnabled(), isAdmin, pm);
   1056 
   1057         setTileEnabled(new ComponentName(packageName,
   1058                 Settings.SimSettingsActivity.class.getName()),
   1059                 Utils.showSimCardTile(this), isAdmin, pm);
   1060 
   1061         setTileEnabled(new ComponentName(packageName,
   1062                 Settings.PowerUsageSummaryActivity.class.getName()),
   1063                 mBatteryPresent, isAdmin, pm);
   1064 
   1065         setTileEnabled(new ComponentName(packageName,
   1066                 Settings.UserSettingsActivity.class.getName()),
   1067                 UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
   1068                 && !Utils.isMonkeyRunning(), isAdmin, pm);
   1069 
   1070         setTileEnabled(new ComponentName(packageName,
   1071                         Settings.WirelessSettingsActivity.class.getName()),
   1072                 !UserManager.isDeviceInDemoMode(this), isAdmin, pm);
   1073 
   1074         setTileEnabled(new ComponentName(packageName,
   1075                         Settings.DateTimeSettingsActivity.class.getName()),
   1076                 !UserManager.isDeviceInDemoMode(this), isAdmin, pm);
   1077         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
   1078         setTileEnabled(new ComponentName(packageName,
   1079                         Settings.PaymentSettingsActivity.class.getName()),
   1080                 pm.hasSystemFeature(PackageManager.FEATURE_NFC)
   1081                         && pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
   1082                         && adapter != null && adapter.isEnabled(), isAdmin, pm);
   1083 
   1084         setTileEnabled(new ComponentName(packageName,
   1085                 Settings.PrintSettingsActivity.class.getName()),
   1086                 pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin, pm);
   1087 
   1088         final boolean showDev = mDevelopmentPreferences.getBoolean(
   1089                     DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng"))
   1090                 && !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
   1091         setTileEnabled(new ComponentName(packageName,
   1092                         Settings.DevelopmentSettingsActivity.class.getName()),
   1093                 showDev, isAdmin, pm);
   1094 
   1095         // Reveal development-only quick settings tiles
   1096         DevelopmentTiles.setTilesEnabled(this, showDev);
   1097 
   1098         if (UserHandle.MU_ENABLED && !isAdmin) {
   1099             // When on restricted users, disable all extra categories (but only the settings ones).
   1100             List<DashboardCategory> categories = getDashboardCategories();
   1101             for (DashboardCategory category : categories) {
   1102                 for (Tile tile : category.tiles) {
   1103                     ComponentName component = tile.intent.getComponent();
   1104                     if (packageName.equals(component.getPackageName()) && !ArrayUtils.contains(
   1105                             SETTINGS_FOR_RESTRICTED, component.getClassName())) {
   1106                         setTileEnabled(component, false, isAdmin, pm);
   1107                     }
   1108                 }
   1109             }
   1110         }
   1111 
   1112         String backupIntent = getResources().getString(R.string.config_backup_settings_intent);
   1113         boolean useDefaultBackup = TextUtils.isEmpty(backupIntent);
   1114         setTileEnabled(new ComponentName(packageName,
   1115                 Settings.PrivacySettingsActivity.class.getName()), useDefaultBackup, isAdmin, pm);
   1116         boolean hasBackupActivity = false;
   1117         if (!useDefaultBackup) {
   1118             try {
   1119                 Intent intent = Intent.parseUri(backupIntent, 0);
   1120                 hasBackupActivity = !getPackageManager().queryIntentActivities(intent, 0).isEmpty();
   1121             } catch (URISyntaxException e) {
   1122                 Log.e(LOG_TAG, "Invalid backup intent URI!", e);
   1123             }
   1124         }
   1125         setTileEnabled(new ComponentName(packageName,
   1126                 BackupSettingsActivity.class.getName()), hasBackupActivity, isAdmin, pm);
   1127 
   1128     }
   1129 
   1130     private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin,
   1131                                 PackageManager pm) {
   1132         if (UserHandle.MU_ENABLED && !isAdmin && getPackageName().equals(component.getPackageName())
   1133                 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, component.getClassName())) {
   1134             enabled = false;
   1135         }
   1136         setTileEnabled(component, enabled);
   1137     }
   1138 
   1139     private void getMetaData() {
   1140         try {
   1141             ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
   1142                     PackageManager.GET_META_DATA);
   1143             if (ai == null || ai.metaData == null) return;
   1144             mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
   1145         } catch (NameNotFoundException nnfe) {
   1146             // No recovery
   1147             Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
   1148         }
   1149     }
   1150 
   1151     // give subclasses access to the Next button
   1152     public boolean hasNextButton() {
   1153         return mNextButton != null;
   1154     }
   1155 
   1156     public Button getNextButton() {
   1157         return mNextButton;
   1158     }
   1159 
   1160     @Override
   1161     public boolean shouldUpRecreateTask(Intent targetIntent) {
   1162         return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
   1163     }
   1164 
   1165     @Override
   1166     public boolean onQueryTextSubmit(String query) {
   1167         switchToSearchResultsFragmentIfNeeded();
   1168         mSearchQuery = query;
   1169         return mSearchResultsFragment.onQueryTextSubmit(query);
   1170     }
   1171 
   1172     @Override
   1173     public boolean onQueryTextChange(String newText) {
   1174         mSearchQuery = newText;
   1175         if (mSearchResultsFragment == null) {
   1176             return false;
   1177         }
   1178         return mSearchResultsFragment.onQueryTextChange(newText);
   1179     }
   1180 
   1181     @Override
   1182     public boolean onClose() {
   1183         return false;
   1184     }
   1185 
   1186     @Override
   1187     public boolean onMenuItemActionExpand(MenuItem item) {
   1188         if (item.getItemId() == mSearchMenuItem.getItemId()) {
   1189             switchToSearchResultsFragmentIfNeeded();
   1190         }
   1191         return true;
   1192     }
   1193 
   1194     @Override
   1195     public boolean onMenuItemActionCollapse(MenuItem item) {
   1196         if (item.getItemId() == mSearchMenuItem.getItemId()) {
   1197             if (mSearchMenuItemExpanded) {
   1198                 revertToInitialFragment();
   1199             }
   1200         }
   1201         return true;
   1202     }
   1203 
   1204     @Override
   1205     protected void onTileClicked(Tile tile) {
   1206         if (mIsShowingDashboard) {
   1207             // If on dashboard, don't finish so the back comes back to here.
   1208             openTile(tile);
   1209         } else {
   1210             super.onTileClicked(tile);
   1211         }
   1212     }
   1213 
   1214     @Override
   1215     public void onProfileTileOpen() {
   1216         if (!mIsShowingDashboard) {
   1217             finish();
   1218         }
   1219     }
   1220 
   1221     private void switchToSearchResultsFragmentIfNeeded() {
   1222         if (mSearchResultsFragment != null) {
   1223             return;
   1224         }
   1225         Fragment current = getFragmentManager().findFragmentById(R.id.main_content);
   1226         if (current != null && current instanceof SearchResultsSummary) {
   1227             mSearchResultsFragment = (SearchResultsSummary) current;
   1228         } else {
   1229             setContentHeaderView(null);
   1230             mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
   1231                     SearchResultsSummary.class.getName(), null, false, true,
   1232                     R.string.search_results_title, null, true);
   1233         }
   1234         mSearchResultsFragment.setSearchView(mSearchView);
   1235         mSearchMenuItemExpanded = true;
   1236     }
   1237 
   1238     public void needToRevertToInitialFragment() {
   1239         mNeedToRevertToInitialFragment = true;
   1240     }
   1241 
   1242     private void revertToInitialFragment() {
   1243         mNeedToRevertToInitialFragment = false;
   1244         mSearchResultsFragment = null;
   1245         mSearchMenuItemExpanded = false;
   1246         getFragmentManager().popBackStackImmediate(SettingsActivity.BACK_STACK_PREFS,
   1247                 FragmentManager.POP_BACK_STACK_INCLUSIVE);
   1248         if (mSearchMenuItem != null) {
   1249             mSearchMenuItem.collapseActionView();
   1250         }
   1251     }
   1252 
   1253     public Intent getResultIntentData() {
   1254         return mResultIntentData;
   1255     }
   1256 
   1257     public void setResultIntentData(Intent resultIntentData) {
   1258         mResultIntentData = resultIntentData;
   1259     }
   1260 
   1261     public void startSuggestion(Intent intent) {
   1262         mCurrentSuggestion = intent.getComponent();
   1263         startActivityForResult(intent, REQUEST_SUGGESTION);
   1264     }
   1265 
   1266     @Override
   1267     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   1268         if (requestCode == REQUEST_SUGGESTION && mCurrentSuggestion != null
   1269                 && resultCode != RESULT_CANCELED) {
   1270             getPackageManager().setComponentEnabledSetting(mCurrentSuggestion,
   1271                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
   1272         }
   1273         super.onActivityResult(requestCode, resultCode, data);
   1274     }
   1275 
   1276 }
   1277