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