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