OSDN Git Service

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