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