OSDN Git Service

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