OSDN Git Service

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