2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
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;
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;
134 import java.net.URISyntaxException;
135 import java.util.ArrayList;
136 import java.util.List;
137 import java.util.Set;
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 {
146 private static final String LOG_TAG = "Settings";
148 private static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
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";
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
165 public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
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
173 public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
176 * Fragment "key" argument passed thru {@link #EXTRA_SHOW_FRAGMENT_ARGUMENTS}
178 public static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
180 public static final String BACK_STACK_PREFS = ":settings:prefs";
182 // extras that allow any preference activity to be launched as part of a wizard
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";
188 // add a Skip button?
189 private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
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";
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
201 public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
203 * The package name used to resolve the title resource id.
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";
212 public static final String EXTRA_SHOW_FRAGMENT_AS_SUBSETTING =
213 ":settings:show_fragment_as_subsetting";
215 public static final String EXTRA_HIDE_DRAWER = ":settings:hide_drawer";
217 public static final String META_DATA_KEY_FRAGMENT_CLASS =
218 "com.android.settings.FRAGMENT_CLASS";
220 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
222 private static final String EMPTY_QUERY = "";
224 private static final int REQUEST_SUGGESTION = 42;
226 private String mFragmentClass;
228 private CharSequence mInitialTitle;
229 private int mInitialTitleResId;
231 // Show only these settings for restricted users
232 private String[] SETTINGS_FOR_RESTRICTED = {
234 WifiSettingsActivity.class.getName(),
235 Settings.BluetoothSettingsActivity.class.getName(),
236 Settings.DataUsageSummaryActivity.class.getName(),
237 Settings.SimSettingsActivity.class.getName(),
238 Settings.WirelessSettingsActivity.class.getName(),
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(),
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(),
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(),
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(),
359 private static final String[] LIKE_SHORTCUT_INTENT_ACTION_ARRAY = {
360 "android.settings.APPLICATION_DETAILS_SETTINGS"
363 private SharedPreferences mDevelopmentPreferences;
364 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
366 private boolean mBatteryPresent = true;
367 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
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);
374 if (mBatteryPresent != batteryPresent) {
375 mBatteryPresent = batteryPresent;
382 private final BroadcastReceiver mUserAddRemoveReceiver = new BroadcastReceiver() {
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();
393 private final DynamicIndexableContentMonitor mDynamicIndexableContentMonitor =
394 new DynamicIndexableContentMonitor();
396 private ActionBar mActionBar;
397 private SwitchBar mSwitchBar;
399 private Button mNextButton;
401 private boolean mDisplayHomeAsUpEnabled;
402 private boolean mDisplaySearch;
404 private boolean mIsShowingDashboard;
405 private boolean mIsShortcut;
407 private ViewGroup mContent;
409 private SearchView mSearchView;
410 private MenuItem mSearchMenuItem;
411 private boolean mSearchMenuItemExpanded = false;
412 private SearchResultsSummary mSearchResultsFragment;
413 private String mSearchQuery;
416 private ArrayList<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
418 private static final String MSG_DATA_FORCE_REFRESH = "msg_data_force_refresh";
420 private boolean mNeedToRevertToInitialFragment = false;
422 private Intent mResultIntentData;
423 private ComponentName mCurrentSuggestion;
425 public SwitchBar getSwitchBar() {
430 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
431 startPreferencePanel(pref.getFragment(), pref.getExtras(), -1, pref.getTitle(),
437 public boolean onPreferenceTreeClick(Preference preference) {
442 public void onConfigurationChanged(Configuration newConfig) {
443 super.onConfigurationChanged(newConfig);
444 Index.getInstance(this).update();
448 public boolean onCreateOptionsMenu(Menu menu) {
449 if (!mDisplaySearch) {
453 MenuInflater inflater = getMenuInflater();
454 inflater.inflate(R.menu.options_menu, menu);
456 // Cache the search query (can be overriden by the OnQueryTextListener)
457 final String query = mSearchQuery;
459 mSearchMenuItem = menu.findItem(R.id.search);
460 mSearchView = (SearchView) mSearchMenuItem.getActionView();
462 if (mSearchMenuItem == null || mSearchView == null) {
466 if (mSearchResultsFragment != null) {
467 mSearchResultsFragment.setSearchView(mSearchView);
470 mSearchMenuItem.setOnActionExpandListener(this);
471 mSearchView.setOnQueryTextListener(this);
472 mSearchView.setOnCloseListener(this);
474 if (mSearchMenuItemExpanded) {
475 mSearchMenuItem.expandActionView();
477 mSearchView.setQuery(query, true /* submit */);
483 public SharedPreferences getSharedPreferences(String name, int mode) {
484 if (name.equals(getPackageName() + "_preferences")) {
485 return new SharedPreferencesLogger(this, getMetricsTag());
487 return super.getSharedPreferences(name, mode);
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);
495 if (tag.startsWith("com.android.settings.")) {
496 tag = tag.replace("com.android.settings.", "");
501 private static boolean isShortCutIntent(final Intent intent) {
502 Set<String> categories = intent.getCategories();
503 return (categories != null) && categories.contains("com.android.settings.SHORTCUT");
506 private static boolean isLikeShortCutIntent(final Intent intent) {
507 String action = intent.getAction();
508 if (action == null) {
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;
518 protected void onCreate(Bundle savedState) {
519 super.onCreate(savedState);
520 long startTime = System.currentTimeMillis();
522 // Should happen before any call to getIntent()
525 final Intent intent = getIntent();
526 if (intent.hasExtra(EXTRA_UI_OPTIONS)) {
527 getWindow().setUiOptions(intent.getIntExtra(EXTRA_UI_OPTIONS, 0));
529 if (intent.getBooleanExtra(EXTRA_HIDE_DRAWER, false)) {
530 setIsDrawerPresent(false);
533 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
534 Context.MODE_PRIVATE);
536 // Getting Intent properties can only be done after the super.onCreate(...)
537 final String initialFragmentName = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
539 mIsShortcut = isShortCutIntent(intent) || isLikeShortCutIntent(intent) ||
540 intent.getBooleanExtra(EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, false);
542 final ComponentName cn = intent.getComponent();
543 final String className = cn.getClassName();
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());
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);
557 // If this is a sub settings, then apply the SubSettings Theme for the ActionBar content insets
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);
567 setContentView(mIsShowingDashboard ?
568 R.layout.settings_main_dashboard : R.layout.settings_main_prefs);
570 mContent = (ViewGroup) findViewById(R.id.main_content);
572 getFragmentManager().addOnBackStackChangedListener(this);
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");
582 Log.w(LOG_TAG, "Cannot update the Indexer as we are running low on storage space!");
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);
593 ArrayList<DashboardCategory> categories =
594 savedState.getParcelableArrayList(SAVE_KEY_CATEGORIES);
595 if (categories != null) {
597 mCategories.addAll(categories);
598 setTitleFromBackStack();
601 mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
602 mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
605 if (!mIsShowingDashboard) {
606 mDisplaySearch = false;
607 // UP will be shown only if it is a sub settings
609 mDisplayHomeAsUpEnabled = isSubSettings;
610 } else if (isSubSettings) {
611 mDisplayHomeAsUpEnabled = true;
613 mDisplayHomeAsUpEnabled = false;
615 setTitleFromIntent(intent);
617 Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
618 switchToFragment(initialFragmentName, initialArguments, true, false,
619 mInitialTitleResId, mInitialTitle, false);
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;
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));
632 switchToFragment(DashboardContainerFragment.class.getName(), args, false, false,
633 mInitialTitleResId, mInitialTitle, false);
637 mActionBar = getActionBar();
638 if (mActionBar != null) {
639 mActionBar.setDisplayHomeAsUpEnabled(mDisplayHomeAsUpEnabled);
640 mActionBar.setHomeButtonEnabled(mDisplayHomeAsUpEnabled);
642 mSwitchBar = (SwitchBar) findViewById(R.id.switch_bar);
643 if (mSwitchBar != null) {
644 mSwitchBar.setMetricsTag(getMetricsTag());
647 // see if we should show Back/Next buttons
648 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
650 View buttonBar = findViewById(R.id.button_bar);
651 if (buttonBar != null) {
652 buttonBar.setVisibility(View.VISIBLE);
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());
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());
668 mNextButton = (Button)findViewById(R.id.next_button);
669 mNextButton.setOnClickListener(new OnClickListener() {
670 public void onClick(View v) {
671 setResult(RESULT_OK, getResultIntentData());
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);
683 mNextButton.setText(buttonText);
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);
692 backButton.setText(buttonText);
695 if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
696 skipButton.setVisibility(View.VISIBLE);
701 if (DEBUG_TIMING) Log.d(LOG_TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
705 public void setDisplaySearchMenu(boolean displaySearch) {
706 if (displaySearch != mDisplaySearch) {
707 mDisplaySearch = displaySearch;
708 invalidateOptionsMenu();
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;
718 final String initialTitleResPackageName = intent.getStringExtra(
719 EXTRA_SHOW_FRAGMENT_TITLE_RES_PACKAGE_NAME);
720 if (initialTitleResPackageName != null) {
722 Context authContext = createPackageContextAsUser(initialTitleResPackageName,
723 0 /* flags */, new UserHandle(UserHandle.myUserId()));
724 mInitialTitle = authContext.getResources().getText(mInitialTitleResId);
725 setTitle(mInitialTitle);
726 mInitialTitleResId = -1;
728 } catch (NameNotFoundException e) {
729 Log.w(LOG_TAG, "Could not find package" + initialTitleResPackageName);
732 setTitle(mInitialTitleResId);
735 mInitialTitleResId = -1;
736 final String initialTitle = intent.getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE);
737 mInitialTitle = (initialTitle != null) ? initialTitle : getTitle();
738 setTitle(mInitialTitle);
743 public void onBackStackChanged() {
744 setTitleFromBackStack();
747 private void setTitleFromBackStack() {
748 final int count = getFragmentManager().getBackStackEntryCount();
751 if (mInitialTitleResId > 0) {
752 setTitle(mInitialTitleResId);
754 setTitle(mInitialTitle);
759 FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1);
760 setTitleFromBackStackEntry(bse);
763 private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) {
764 final CharSequence title;
765 final int titleRes = bse.getBreadCrumbTitleRes();
767 title = getText(titleRes);
769 title = bse.getBreadCrumbTitle();
777 protected void onSaveInstanceState(Bundle outState) {
778 super.onSaveInstanceState(outState);
780 if (mCategories.size() > 0) {
781 outState.putParcelableArrayList(SAVE_KEY_CATEGORIES, mCategories);
784 outState.putBoolean(SAVE_KEY_SHOW_HOME_AS_UP, mDisplayHomeAsUpEnabled);
785 outState.putBoolean(SAVE_KEY_SHOW_SEARCH, mDisplaySearch);
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);
796 String query = (mSearchView != null) ? mSearchView.getQuery().toString() : EMPTY_QUERY;
797 outState.putString(SAVE_KEY_SEARCH_QUERY, query);
802 protected void onStart() {
805 if (mNeedToRevertToInitialFragment) {
806 revertToInitialFragment();
809 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
811 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
815 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
816 mDevelopmentPreferencesListener);
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));
822 mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
824 if(mDisplaySearch && !TextUtils.isEmpty(mSearchQuery)) {
825 onQueryTextSubmit(mSearchQuery);
831 protected void onStop() {
833 unregisterReceiver(mBatteryInfoReceiver);
834 unregisterReceiver(mUserAddRemoveReceiver);
835 mDynamicIndexableContentMonitor.unregister();
839 public void onDestroy() {
842 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
843 mDevelopmentPreferencesListener);
844 mDevelopmentPreferencesListener = null;
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;
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();
867 args = new Bundle(args);
871 args.putParcelable("intent", superIntent);
872 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
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.
882 private String getStartingFragmentClass(Intent intent) {
883 if (mFragmentClass != null) return mFragmentClass;
885 String intentClass = intent.getComponent().getClassName();
886 if (intentClass.equals(getClass().getName())) return null;
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();
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
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
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.
917 public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
918 CharSequence titleText, Fragment resultTo, int resultRequestCode) {
921 if (titleText != null) {
922 title = titleText.toString();
924 // There not much we can do in that case
928 Utils.startWithFragment(this, fragmentClass, args, resultTo, resultRequestCode,
929 titleRes, title, mIsShortcut);
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.
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.
944 public void startPreferencePanelAsUser(String fragmentClass, Bundle args, int titleRes,
945 CharSequence titleText, UserHandle userHandle) {
946 // This is a workaround.
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.
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);
961 if (titleText != null) {
962 title = titleText.toString();
964 // There not much we can do in that case
968 Utils.startWithFragmentAsUser(this, fragmentClass, args,
969 titleRes, title, mIsShortcut, userHandle);
974 * Called by a preference panel fragment to finish itself.
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.
982 public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {
983 setResult(resultCode, resultData);
988 * Start a new fragment.
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.
994 public void startPreferenceFragment(Fragment fragment, boolean push) {
995 FragmentTransaction transaction = getFragmentManager().beginTransaction();
996 transaction.replace(R.id.main_content, fragment);
998 transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
999 transaction.addToBackStack(BACK_STACK_PREFS);
1001 transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
1003 transaction.commitAllowingStateLoss();
1007 * Switch to a specific Fragment with taking care of validation, Title and BackStack
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: "
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);
1021 if (addToBackStack) {
1022 transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS);
1024 if (titleResId > 0) {
1025 transaction.setBreadCrumbTitle(titleResId);
1026 } else if (title != null) {
1027 transaction.setBreadCrumbTitle(title);
1029 transaction.commitAllowingStateLoss();
1030 getFragmentManager().executePendingTransactions();
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() {
1041 doUpdateTilesList();
1046 private void doUpdateTilesList() {
1047 PackageManager pm = getPackageManager();
1048 final UserManager um = UserManager.get(this);
1049 final boolean isAdmin = um.isAdminUser();
1051 String packageName = getPackageName();
1052 setTileEnabled(new ComponentName(packageName, WifiSettingsActivity.class.getName()),
1053 pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin, pm);
1055 setTileEnabled(new ComponentName(packageName,
1056 Settings.BluetoothSettingsActivity.class.getName()),
1057 pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin, pm);
1059 setTileEnabled(new ComponentName(packageName,
1060 Settings.DataUsageSummaryActivity.class.getName()),
1061 Utils.isBandwidthControlEnabled(), isAdmin, pm);
1063 setTileEnabled(new ComponentName(packageName,
1064 Settings.SimSettingsActivity.class.getName()),
1065 Utils.showSimCardTile(this), isAdmin, pm);
1067 setTileEnabled(new ComponentName(packageName,
1068 Settings.PowerUsageSummaryActivity.class.getName()),
1069 mBatteryPresent, isAdmin, pm);
1071 setTileEnabled(new ComponentName(packageName,
1072 Settings.UserSettingsActivity.class.getName()),
1073 UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
1074 && !Utils.isMonkeyRunning(), isAdmin, pm);
1076 setTileEnabled(new ComponentName(packageName,
1077 Settings.WirelessSettingsActivity.class.getName()),
1078 !UserManager.isDeviceInDemoMode(this), isAdmin, pm);
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);
1090 setTileEnabled(new ComponentName(packageName,
1091 Settings.PrintSettingsActivity.class.getName()),
1092 pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin, pm);
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);
1101 // Reveal development-only quick settings tiles
1102 DevelopmentTiles.setTilesEnabled(this, showDev);
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);
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) {
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);
1131 setTileEnabled(new ComponentName(packageName,
1132 BackupSettingsActivity.class.getName()), hasBackupActivity, isAdmin, pm);
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())) {
1142 setTileEnabled(component, enabled);
1145 private void getMetaData() {
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) {
1153 Log.d(LOG_TAG, "Cannot get Metadata for: " + getComponentName().toString());
1157 // give subclasses access to the Next button
1158 public boolean hasNextButton() {
1159 return mNextButton != null;
1162 public Button getNextButton() {
1167 public boolean shouldUpRecreateTask(Intent targetIntent) {
1168 return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
1172 public boolean onQueryTextSubmit(String query) {
1173 switchToSearchResultsFragmentIfNeeded();
1174 mSearchQuery = query;
1175 return mSearchResultsFragment.onQueryTextSubmit(query);
1179 public boolean onQueryTextChange(String newText) {
1180 mSearchQuery = newText;
1181 if (mSearchResultsFragment == null) {
1184 return mSearchResultsFragment.onQueryTextChange(newText);
1188 public boolean onClose() {
1193 public boolean onMenuItemActionExpand(MenuItem item) {
1194 if (item.getItemId() == mSearchMenuItem.getItemId()) {
1195 switchToSearchResultsFragmentIfNeeded();
1201 public boolean onMenuItemActionCollapse(MenuItem item) {
1202 if (item.getItemId() == mSearchMenuItem.getItemId()) {
1203 if (mSearchMenuItemExpanded) {
1204 revertToInitialFragment();
1211 protected void onTileClicked(Tile tile) {
1212 if (mIsShowingDashboard) {
1213 // If on dashboard, don't finish so the back comes back to here.
1216 super.onTileClicked(tile);
1221 public void onProfileTileOpen() {
1222 if (!mIsShowingDashboard) {
1227 private void switchToSearchResultsFragmentIfNeeded() {
1228 if (mSearchResultsFragment != null) {
1231 Fragment current = getFragmentManager().findFragmentById(R.id.main_content);
1232 if (current != null && current instanceof SearchResultsSummary) {
1233 mSearchResultsFragment = (SearchResultsSummary) current;
1235 setContentHeaderView(null);
1236 mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
1237 SearchResultsSummary.class.getName(), null, false, true,
1238 R.string.search_results_title, null, true);
1240 mSearchResultsFragment.setSearchView(mSearchView);
1241 mSearchMenuItemExpanded = true;
1244 public void needToRevertToInitialFragment() {
1245 mNeedToRevertToInitialFragment = true;
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();
1259 public Intent getResultIntentData() {
1260 return mResultIntentData;
1263 public void setResultIntentData(Intent resultIntentData) {
1264 mResultIntentData = resultIntentData;
1267 public void startSuggestion(Intent intent) {
1268 mCurrentSuggestion = intent.getComponent();
1269 startActivityForResult(intent, REQUEST_SUGGESTION);
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);
1279 super.onActivityResult(requestCode, resultCode, data);