OSDN Git Service

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