OSDN Git Service

resolve merge conflicts of d5b3a5d to nyc-mr1-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
53 import com.android.internal.util.ArrayUtils;
54 import com.android.settings.Settings.WifiSettingsActivity;
55 import com.android.settings.accessibility.AccessibilitySettings;
56 import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
57 import com.android.settings.accessibility.CaptionPropertiesFragment;
58 import com.android.settings.accounts.AccountSettings;
59 import com.android.settings.accounts.AccountSyncSettings;
60 import com.android.settings.accounts.ManagedProfileSettings;
61 import com.android.settings.applications.AdvancedAppSettings;
62 import com.android.settings.applications.DrawOverlayDetails;
63 import com.android.settings.applications.InstalledAppDetails;
64 import com.android.settings.applications.ManageApplications;
65 import com.android.settings.applications.ManageAssist;
66 import com.android.settings.applications.NotificationApps;
67 import com.android.settings.applications.ProcessStatsSummary;
68 import com.android.settings.applications.ProcessStatsUi;
69 import com.android.settings.applications.UsageAccessDetails;
70 import com.android.settings.applications.WriteSettingsDetails;
71 import com.android.settings.applications.VrListenerSettings;
72 import com.android.settings.bluetooth.BluetoothSettings;
73 import com.android.settings.dashboard.DashboardContainerFragment;
74 import com.android.settings.dashboard.SearchResultsSummary;
75 import com.android.settings.datausage.DataUsageSummary;
76 import com.android.settings.deviceinfo.PrivateVolumeForget;
77 import com.android.settings.deviceinfo.PrivateVolumeSettings;
78 import com.android.settings.deviceinfo.PublicVolumeSettings;
79 import com.android.settings.deviceinfo.StorageSettings;
80 import com.android.settings.fuelgauge.BatterySaverSettings;
81 import com.android.settings.fuelgauge.PowerUsageDetail;
82 import com.android.settings.fuelgauge.PowerUsageSummary;
83 import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
84 import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
85 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
86 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment2;
87 import com.android.settings.inputmethod.PhysicalKeyboardFragment;
88 import com.android.settings.inputmethod.SpellCheckersSettings;
89 import com.android.settings.inputmethod.UserDictionaryList;
90 import com.android.settings.localepicker.LocaleListEditor;
91 import com.android.settings.location.LocationSettings;
92 import com.android.settings.nfc.AndroidBeam;
93 import com.android.settings.nfc.PaymentSettings;
94 import com.android.settings.notification.AppNotificationSettings;
95 import com.android.settings.notification.ConfigureNotificationSettings;
96 import com.android.settings.notification.NotificationAccessSettings;
97 import com.android.settings.notification.NotificationStation;
98 import com.android.settings.notification.OtherSoundSettings;
99 import com.android.settings.notification.SoundSettings;
100 import com.android.settings.notification.ZenAccessSettings;
101 import com.android.settings.notification.ZenModeAutomationSettings;
102 import com.android.settings.notification.ZenModeEventRuleSettings;
103 import com.android.settings.notification.ZenModePrioritySettings;
104 import com.android.settings.notification.ZenModeScheduleRuleSettings;
105 import com.android.settings.notification.ZenModeSettings;
106 import com.android.settings.notification.ZenModeVisualInterruptionSettings;
107 import com.android.settings.overlay.FeatureFactory;
108 import com.android.settings.print.PrintJobSettingsFragment;
109 import com.android.settings.print.PrintSettingsFragment;
110 import com.android.settings.qstile.DevelopmentTiles;
111 import com.android.settings.search.DynamicIndexableContentMonitor;
112 import com.android.settings.search.Index;
113 import com.android.settings.sim.SimSettings;
114 import com.android.settings.tts.TextToSpeechSettings;
115 import com.android.settings.users.UserSettings;
116 import com.android.settings.vpn2.VpnSettings;
117 import com.android.settings.wfd.WifiDisplaySettings;
118 import com.android.settings.widget.SwitchBar;
119 import com.android.settings.wifi.AdvancedWifiSettings;
120 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
121 import com.android.settings.wifi.WifiSettings;
122 import com.android.settings.wifi.p2p.WifiP2pSettings;
123 import com.android.settingslib.drawer.DashboardCategory;
124 import com.android.settingslib.drawer.SettingsDrawerActivity;
125 import com.android.settingslib.drawer.Tile;
126
127 import java.util.ArrayList;
128 import java.util.List;
129 import java.util.Set;
130
131 public class SettingsActivity extends SettingsDrawerActivity
132         implements PreferenceManager.OnPreferenceTreeClickListener,
133         PreferenceFragment.OnPreferenceStartFragmentCallback,
134         ButtonBarHandler, FragmentManager.OnBackStackChangedListener,
135         SearchView.OnQueryTextListener, SearchView.OnCloseListener,
136         MenuItem.OnActionExpandListener {
137
138     private static final String LOG_TAG = "Settings";
139
140     private static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
141
142     // Constants for state save/restore
143     private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
144     private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
145     private static final String SAVE_KEY_SEARCH_QUERY = ":settings:search_query";
146     private static final String SAVE_KEY_SHOW_HOME_AS_UP = ":settings:show_home_as_up";
147     private static final String SAVE_KEY_SHOW_SEARCH = ":settings:show_search";
148     private static final String SAVE_KEY_HOME_ACTIVITIES_COUNT = ":settings:home_activities_count";
149
150     /**
151      * When starting this activity, the invoking Intent can contain this extra
152      * string to specify which fragment should be initially displayed.
153      * <p/>Starting from Key Lime Pie, when this argument is passed in, the activity
154      * will call isValidFragment() to confirm that the fragment class name is valid for this
155      * activity.
156      */
157     public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
158
159     /**
160      * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
161      * this extra can also be specified to supply a Bundle of arguments to pass
162      * to that fragment when it is instantiated during the initial creation
163      * of the activity.
164      */
165     public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
166
167     /**
168      * Fragment "key" argument passed thru {@link #EXTRA_SHOW_FRAGMENT_ARGUMENTS}
169      */
170     public static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
171
172     public static final String BACK_STACK_PREFS = ":settings:prefs";
173
174     // extras that allow any preference activity to be launched as part of a wizard
175
176     // show Back and Next buttons? takes boolean parameter
177     // Back will then return RESULT_CANCELED and Next RESULT_OK
178     protected static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
179
180     // add a Skip button?
181     private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
182
183     // specify custom text for the Back or Next buttons, or cause a button to not appear
184     // at all by setting it to null
185     protected static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
186     protected static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
187
188     /**
189      * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
190      * those extra can also be specify to supply the title or title res id to be shown for
191      * that fragment.
192      */
193     public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
194     /**
195      * The package name used to resolve the title resource id.
196      */
197     public static final String EXTRA_SHOW_FRAGMENT_TITLE_RES_PACKAGE_NAME =
198             ":settings:show_fragment_title_res_package_name";
199     public static final String EXTRA_SHOW_FRAGMENT_TITLE_RESID =
200             ":settings:show_fragment_title_resid";
201     public static final String EXTRA_SHOW_FRAGMENT_AS_SHORTCUT =
202             ":settings:show_fragment_as_shortcut";
203
204     public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
205             ":settings:show_fragment_as_subsetting";
206
207     public static final String EXTRA_HIDE_DRAWER = ":settings:hide_drawer";
208
209     public static final String META_DATA_KEY_FRAGMENT_CLASS =
210         "com.android.settings.FRAGMENT_CLASS";
211
212     private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
213
214     private static final String EMPTY_QUERY = "";
215
216     private static final int REQUEST_SUGGESTION = 42;
217
218     private String mFragmentClass;
219
220     private CharSequence mInitialTitle;
221     private int mInitialTitleResId;
222
223     // Show only these settings for restricted users
224     private String[] SETTINGS_FOR_RESTRICTED = {
225             //wireless_section
226             WifiSettingsActivity.class.getName(),
227             Settings.BluetoothSettingsActivity.class.getName(),
228             Settings.DataUsageSummaryActivity.class.getName(),
229             Settings.SimSettingsActivity.class.getName(),
230             Settings.WirelessSettingsActivity.class.getName(),
231             //device_section
232             Settings.HomeSettingsActivity.class.getName(),
233             Settings.SoundSettingsActivity.class.getName(),
234             Settings.DisplaySettingsActivity.class.getName(),
235             Settings.StorageSettingsActivity.class.getName(),
236             Settings.ManageApplicationsActivity.class.getName(),
237             Settings.PowerUsageSummaryActivity.class.getName(),
238             //personal_section
239             Settings.LocationSettingsActivity.class.getName(),
240             Settings.SecuritySettingsActivity.class.getName(),
241             Settings.InputMethodAndLanguageSettingsActivity.class.getName(),
242             Settings.UserSettingsActivity.class.getName(),
243             Settings.AccountSettingsActivity.class.getName(),
244             //system_section
245             Settings.DateTimeSettingsActivity.class.getName(),
246             Settings.DeviceInfoSettingsActivity.class.getName(),
247             Settings.AccessibilitySettingsActivity.class.getName(),
248             Settings.PrintSettingsActivity.class.getName(),
249             Settings.PaymentSettingsActivity.class.getName(),
250     };
251
252     private static final String[] ENTRY_FRAGMENTS = {
253             WirelessSettings.class.getName(),
254             WifiSettings.class.getName(),
255             AdvancedWifiSettings.class.getName(),
256             SavedAccessPointsWifiSettings.class.getName(),
257             BluetoothSettings.class.getName(),
258             SimSettings.class.getName(),
259             TetherSettings.class.getName(),
260             WifiP2pSettings.class.getName(),
261             VpnSettings.class.getName(),
262             DateTimeSettings.class.getName(),
263             LocaleListEditor.class.getName(),
264             InputMethodAndLanguageSettings.class.getName(),
265             AvailableVirtualKeyboardFragment.class.getName(),
266             SpellCheckersSettings.class.getName(),
267             UserDictionaryList.class.getName(),
268             UserDictionarySettings.class.getName(),
269             HomeSettings.class.getName(),
270             DisplaySettings.class.getName(),
271             DeviceInfoSettings.class.getName(),
272             ManageApplications.class.getName(),
273             NotificationApps.class.getName(),
274             ManageAssist.class.getName(),
275             ProcessStatsUi.class.getName(),
276             NotificationStation.class.getName(),
277             LocationSettings.class.getName(),
278             SecuritySettings.class.getName(),
279             UsageAccessDetails.class.getName(),
280             PrivacySettings.class.getName(),
281             DeviceAdminSettings.class.getName(),
282             AccessibilitySettings.class.getName(),
283             AccessibilitySettingsForSetupWizard.class.getName(),
284             CaptionPropertiesFragment.class.getName(),
285             com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment.class.getName(),
286             TextToSpeechSettings.class.getName(),
287             StorageSettings.class.getName(),
288             PrivateVolumeForget.class.getName(),
289             PrivateVolumeSettings.class.getName(),
290             PublicVolumeSettings.class.getName(),
291             DevelopmentSettings.class.getName(),
292             AndroidBeam.class.getName(),
293             WifiDisplaySettings.class.getName(),
294             PowerUsageSummary.class.getName(),
295             AccountSyncSettings.class.getName(),
296             AccountSettings.class.getName(),
297             CryptKeeperSettings.class.getName(),
298             DataUsageSummary.class.getName(),
299             DreamSettings.class.getName(),
300             UserSettings.class.getName(),
301             NotificationAccessSettings.class.getName(),
302             ZenAccessSettings.class.getName(),
303             PrintSettingsFragment.class.getName(),
304             PrintJobSettingsFragment.class.getName(),
305             TrustedCredentialsSettings.class.getName(),
306             PaymentSettings.class.getName(),
307             KeyboardLayoutPickerFragment.class.getName(),
308             KeyboardLayoutPickerFragment2.class.getName(),
309             PhysicalKeyboardFragment.class.getName(),
310             ZenModeSettings.class.getName(),
311             SoundSettings.class.getName(),
312             ConfigureNotificationSettings.class.getName(),
313             ChooseLockPassword.ChooseLockPasswordFragment.class.getName(),
314             ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
315             InstalledAppDetails.class.getName(),
316             BatterySaverSettings.class.getName(),
317             AppNotificationSettings.class.getName(),
318             OtherSoundSettings.class.getName(),
319             ApnSettings.class.getName(),
320             WifiCallingSettings.class.getName(),
321             ZenModePrioritySettings.class.getName(),
322             ZenModeAutomationSettings.class.getName(),
323             ZenModeScheduleRuleSettings.class.getName(),
324             ZenModeEventRuleSettings.class.getName(),
325             ZenModeVisualInterruptionSettings.class.getName(),
326             ProcessStatsUi.class.getName(),
327             PowerUsageDetail.class.getName(),
328             ProcessStatsSummary.class.getName(),
329             DrawOverlayDetails.class.getName(),
330             WriteSettingsDetails.class.getName(),
331             AdvancedAppSettings.class.getName(),
332             WallpaperTypeSettings.class.getName(),
333             VrListenerSettings.class.getName(),
334             ManagedProfileSettings.class.getName(),
335     };
336
337
338     private static final String[] LIKE_SHORTCUT_INTENT_ACTION_ARRAY = {
339             "android.settings.APPLICATION_DETAILS_SETTINGS"
340     };
341
342     private SharedPreferences mDevelopmentPreferences;
343     private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
344
345     private boolean mBatteryPresent = true;
346     private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
347         @Override
348         public void onReceive(Context context, Intent intent) {
349             String action = intent.getAction();
350             if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
351                 boolean batteryPresent = Utils.isBatteryPresent(intent);
352
353                 if (mBatteryPresent != batteryPresent) {
354                     mBatteryPresent = batteryPresent;
355                     updateTilesList();
356                 }
357             }
358         }
359     };
360
361     private final BroadcastReceiver mUserAddRemoveReceiver = new BroadcastReceiver() {
362         @Override
363         public void onReceive(Context context, Intent intent) {
364             String action = intent.getAction();
365             if (action.equals(Intent.ACTION_USER_ADDED)
366                     || action.equals(Intent.ACTION_USER_REMOVED)) {
367                 Index.getInstance(getApplicationContext()).update();
368             }
369         }
370     };
371
372     private final DynamicIndexableContentMonitor mDynamicIndexableContentMonitor =
373             new DynamicIndexableContentMonitor();
374
375     private ActionBar mActionBar;
376     private SwitchBar mSwitchBar;
377
378     private Button mNextButton;
379
380     private boolean mDisplayHomeAsUpEnabled;
381     private boolean mDisplaySearch;
382
383     private boolean mIsShowingDashboard;
384     private boolean mIsShortcut;
385
386     private int mMainContentId = R.id.main_content;
387     private ViewGroup mContent;
388
389     private SearchView mSearchView;
390     private MenuItem mSearchMenuItem;
391     private boolean mSearchMenuItemExpanded = false;
392     private SearchResultsSummary mSearchResultsFragment;
393     private String mSearchQuery;
394
395     // Categories
396     private ArrayList<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
397
398     private static final String MSG_DATA_FORCE_REFRESH = "msg_data_force_refresh";
399
400     private boolean mNeedToRevertToInitialFragment = false;
401
402     private Intent mResultIntentData;
403     private ComponentName mCurrentSuggestion;
404
405     public SwitchBar getSwitchBar() {
406         return mSwitchBar;
407     }
408
409     @Override
410     public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
411         // Override the fragment title for Wallpaper settings
412         CharSequence title = pref.getTitle();
413         if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
414             title = getString(R.string.wallpaper_settings_fragment_title);
415         }
416         startPreferencePanel(pref.getFragment(), pref.getExtras(), -1, title,
417                 null, 0);
418         return true;
419     }
420
421     @Override
422     public boolean onPreferenceTreeClick(Preference preference) {
423         return false;
424     }
425
426     @Override
427     public void onConfigurationChanged(Configuration newConfig) {
428         super.onConfigurationChanged(newConfig);
429         Index.getInstance(this).update();
430     }
431
432     @Override
433     protected void onStart() {
434         super.onStart();
435
436         if (mNeedToRevertToInitialFragment) {
437             revertToInitialFragment();
438         }
439     }
440
441     @Override
442     public boolean onCreateOptionsMenu(Menu menu) {
443         if (!mDisplaySearch) {
444             return false;
445         }
446
447         MenuInflater inflater = getMenuInflater();
448         inflater.inflate(R.menu.options_menu, menu);
449
450         // Cache the search query (can be overriden by the OnQueryTextListener)
451         final String query = mSearchQuery;
452
453         mSearchMenuItem = menu.findItem(R.id.search);
454         mSearchView = (SearchView) mSearchMenuItem.getActionView();
455
456         if (mSearchMenuItem == null || mSearchView == null) {
457             return false;
458         }
459
460         if (mSearchResultsFragment != null) {
461             mSearchResultsFragment.setSearchView(mSearchView);
462         }
463
464         mSearchMenuItem.setOnActionExpandListener(this);
465         mSearchView.setOnQueryTextListener(this);
466         mSearchView.setOnCloseListener(this);
467
468         if (mSearchMenuItemExpanded) {
469             mSearchMenuItem.expandActionView();
470         }
471         mSearchView.setQuery(query, true /* submit */);
472
473         return true;
474     }
475
476     @Override
477     public SharedPreferences getSharedPreferences(String name, int mode) {
478         if (name.equals(getPackageName() + "_preferences")) {
479             return new SharedPreferencesLogger(this, getMetricsTag());
480         }
481         return super.getSharedPreferences(name, mode);
482     }
483
484     private String getMetricsTag() {
485         String tag = getClass().getName();
486         if (getIntent() != null && getIntent().hasExtra(EXTRA_SHOW_FRAGMENT)) {
487             tag = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
488         }
489         if (tag.startsWith("com.android.settings.")) {
490             tag = tag.replace("com.android.settings.", "");
491         }
492         return tag;
493     }
494
495     private static boolean isShortCutIntent(final Intent intent) {
496         Set<String> categories = intent.getCategories();
497         return (categories != null) && categories.contains("com.android.settings.SHORTCUT");
498     }
499
500     private static boolean isLikeShortCutIntent(final Intent intent) {
501         String action = intent.getAction();
502         if (action == null) {
503             return false;
504         }
505         for (int i = 0; i < LIKE_SHORTCUT_INTENT_ACTION_ARRAY.length; i++) {
506             if (LIKE_SHORTCUT_INTENT_ACTION_ARRAY[i].equals(action)) return true;
507         }
508         return false;
509     }
510
511     @Override
512     protected void onCreate(Bundle savedState) {
513         super.onCreate(savedState);
514         long startTime = System.currentTimeMillis();
515
516         // Should happen before any call to getIntent()
517         getMetaData();
518
519         final Intent intent = getIntent();
520         if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
521             getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
522         }
523         if (intent.getBooleanExtra(EXTRA_HIDE_DRAWER, false)) {
524             setIsDrawerPresent(false);
525         }
526
527         mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
528                 Context.MODE_PRIVATE);
529
530         // Getting Intent properties can only be done after the super.onCreate(...)
531         final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
532
533         mIsShortcut = isShortCutIntent(intent) || isLikeShortCutIntent(intent) ||
534                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, false);
535
536         final ComponentName cn = intent.getComponent();
537         final String className = cn.getClassName();
538
539         mIsShowingDashboard = className.equals(Settings.class.getName())
540                 || className.equals(Settings.WirelessSettings.class.getName())
541                 || className.equals(Settings.DeviceSettings.class.getName())
542                 || className.equals(Settings.PersonalSettings.class.getName())
543                 || className.equals(Settings.WirelessSettings.class.getName());
544
545         // This is a "Sub Settings" when:
546         // - this is a real SubSettings
547         // - or :settings:show_fragment_as_subsetting is passed to the Intent
548         final boolean isSubSettings = this instanceof SubSettings ||
549                 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SUBSETTING, false);
550
551         // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content insets
552         if (isSubSettings) {
553             // Check also that we are not a Theme Dialog as we don't want to override them
554             final int themeResId = getThemeResId();
555             if (themeResId != R.style.Theme_DialogWhenLarge &&
556                     themeResId != R.style.Theme_SubSettingsDialogWhenLarge) {
557                 setTheme(R.style.Theme_SubSettings);
558             }
559         }
560
561         setContentView(mIsShowingDashboard ?
562                 R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
563
564         mContent = (ViewGroup) findViewById(mMainContentId);
565
566         getFragmentManager().addOnBackStackChangedListener(this);
567
568         if (mIsShowingDashboard) {
569             // Run the Index update only if we have some space
570             if (!Utils.isLowStorage(this)) {
571                 long indexStartTime = System.currentTimeMillis();
572                 Index.getInstance(getApplicationContext()).update();
573                 if (DEBUG_TIMING) Log.d(LOG_TAG, "Index.update() took "
574                         + (System.currentTimeMillis() - indexStartTime) + " ms");
575             } else {
576                 Log.w(LOG_TAG, "Cannot update the Indexer as we are running low on storage space!");
577             }
578         }
579
580         if (savedState != null) {
581             // We are restarting from a previous saved state; used that to initialize, instead
582             // of starting fresh.
583             mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
584             mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
585
586             setTitleFromIntent(intent);
587
588             ArrayList<DashboardCategory> categories =
589                     savedState.getParcelableArrayList(SAVE_KEY_CATEGORIES);
590             if (categories != null) {
591                 mCategories.clear();
592                 mCategories.addAll(categories);
593                 setTitleFromBackStack();
594             }
595
596             mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
597             mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
598         } else {
599             if (!mIsShowingDashboard) {
600                 mDisplaySearch = false;
601                 // UP will be shown only if it is a sub settings
602                 if (mIsShortcut) {
603                     mDisplayHomeAsUpEnabled = isSubSettings;
604                 } else if (isSubSettings) {
605                     mDisplayHomeAsUpEnabled = true;
606                 } else {
607                     mDisplayHomeAsUpEnabled = false;
608                 }
609                 setTitleFromIntent(intent);
610
611                 Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
612                 switchToFragment(initialFragmentName, initialArguments, true, false,
613                         mInitialTitleResId, mInitialTitle, false);
614             } else {
615                 // No UP affordance if we are displaying the main Dashboard
616                 mDisplayHomeAsUpEnabled = false;
617                 // Show Search affordance
618                 mDisplaySearch = true;
619                 mInitialTitleResId = R.string.dashboard_title;
620                 switchToFragment(DashboardContainerFragment.class.getName(), null, false, false,
621                         mInitialTitleResId, mInitialTitle, false);
622             }
623         }
624
625         mActionBar = getActionBar();
626         if (mActionBar != null) {
627             mActionBar.setDisplayHomeAsUpEnabled(mDisplayHomeAsUpEnabled);
628             mActionBar.setHomeButtonEnabled(mDisplayHomeAsUpEnabled);
629         }
630         mSwitchBar = (SwitchBar) findViewById(R.id.switch_bar);
631         if (mSwitchBar != null) {
632             mSwitchBar.setMetricsTag(getMetricsTag());
633         }
634
635         // see if we should show Back/Next buttons
636         if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
637
638             View buttonBar = findViewById(R.id.button_bar);
639             if (buttonBar != null) {
640                 buttonBar.setVisibility(View.VISIBLE);
641
642                 Button backButton = (Button)findViewById(R.id.back_button);
643                 backButton.setOnClickListener(new OnClickListener() {
644                     public void onClick(View v) {
645                         setResult(RESULT_CANCELED, getResultIntentData());
646                         finish();
647                     }
648                 });
649                 Button skipButton = (Button)findViewById(R.id.skip_button);
650                 skipButton.setOnClickListener(new OnClickListener() {
651                     public void onClick(View v) {
652                         setResult(RESULT_OK, getResultIntentData());
653                         finish();
654                     }
655                 });
656                 mNextButton = (Button)findViewById(R.id.next_button);
657                 mNextButton.setOnClickListener(new OnClickListener() {
658                     public void onClick(View v) {
659                         setResult(RESULT_OK, getResultIntentData());
660                         finish();
661                     }
662                 });
663
664                 // set our various button parameters
665                 if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
666                     String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
667                     if (TextUtils.isEmpty(buttonText)) {
668                         mNextButton.setVisibility(View.GONE);
669                     }
670                     else {
671                         mNextButton.setText(buttonText);
672                     }
673                 }
674                 if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
675                     String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
676                     if (TextUtils.isEmpty(buttonText)) {
677                         backButton.setVisibility(View.GONE);
678                     }
679                     else {
680                         backButton.setText(buttonText);
681                     }
682                 }
683                 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
684                     skipButton.setVisibility(View.VISIBLE);
685                 }
686             }
687         }
688
689         if (DEBUG_TIMING) Log.d(LOG_TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
690                 + " ms");
691     }
692
693     /**
694      * Sets the id of the view containing the main content. Should be called before calling super's
695      * onCreate.
696      */
697     protected void setMainContentId(int contentId) {
698         mMainContentId = contentId;
699     }
700
701     private void setTitleFromIntent(Intent intent) {
702         final int initialTitleResId = intent.getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
703         if (initialTitleResId > 0) {
704             mInitialTitle = null;
705             mInitialTitleResId = initialTitleResId;
706
707             final String initialTitleResPackageName = intent.getStringExtra(
708                     EXTRA_SHOW_FRAGMENT_TITLE_RES_PACKAGE_NAME);
709             if (initialTitleResPackageName != null) {
710                 try {
711                     Context authContext = createPackageContextAsUser(initialTitleResPackageName,
712                             0 /* flags */, new UserHandle(UserHandle.myUserId()));
713                     mInitialTitle = authContext.getResources().getText(mInitialTitleResId);
714                     setTitle(mInitialTitle);
715                     mInitialTitleResId = -1;
716                     return;
717                 } catch (NameNotFoundException e) {
718                     Log.w(LOG_TAG, "Could not find package" + initialTitleResPackageName);
719                 }
720             } else {
721                 setTitle(mInitialTitleResId);
722             }
723         } else {
724             mInitialTitleResId = -1;
725             final String initialTitle = intent.getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE);
726             mInitialTitle = (initialTitle != null) ? initialTitle : getTitle();
727             setTitle(mInitialTitle);
728         }
729     }
730
731     @Override
732     public void onBackStackChanged() {
733         setTitleFromBackStack();
734     }
735
736     private void setTitleFromBackStack() {
737         final int count = getFragmentManager().getBackStackEntryCount();
738
739         if (count == 0) {
740             if (mInitialTitleResId > 0) {
741                 setTitle(mInitialTitleResId);
742             } else {
743                 setTitle(mInitialTitle);
744             }
745             return;
746         }
747
748         FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
749         setTitleFromBackStackEntry(bse);
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             setContentHeaderView(null);
1204             mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
1205                     SearchResultsSummary.class.getName(), null, false, true,
1206                     R.string.search_results_title, null, true);
1207         }
1208         mSearchResultsFragment.setSearchView(mSearchView);
1209         mSearchMenuItemExpanded = true;
1210     }
1211
1212     public void needToRevertToInitialFragment() {
1213         mNeedToRevertToInitialFragment = true;
1214     }
1215
1216     private void revertToInitialFragment() {
1217         mNeedToRevertToInitialFragment = false;
1218         mSearchResultsFragment = null;
1219         mSearchMenuItemExpanded = false;
1220         getFragmentManager().popBackStackImmediate(SettingsActivity.BACK_STACK_PREFS,
1221                 FragmentManager.POP_BACK_STACK_INCLUSIVE);
1222         if (mSearchMenuItem != null) {
1223             mSearchMenuItem.collapseActionView();
1224         }
1225     }
1226
1227     public Intent getResultIntentData() {
1228         return mResultIntentData;
1229     }
1230
1231     public void setResultIntentData(Intent resultIntentData) {
1232         mResultIntentData = resultIntentData;
1233     }
1234
1235     public void startSuggestion(Intent intent) {
1236         mCurrentSuggestion = intent.getComponent();
1237         startActivityForResult(intent, REQUEST_SUGGESTION);
1238     }
1239
1240     @Override
1241     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1242         if (requestCode == REQUEST_SUGGESTION && mCurrentSuggestion != null
1243                 && resultCode != RESULT_CANCELED) {
1244             getPackageManager().setComponentEnabledSetting(mCurrentSuggestion,
1245                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
1246         }
1247         super.onActivityResult(requestCode, resultCode, data);
1248     }
1249
1250 }