OSDN Git Service

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