OSDN Git Service

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