OSDN Git Service

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