OSDN Git Service

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