OSDN Git Service

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