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