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