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