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