Settings.java revision c8a9317649d59fb3e2fc7540aedba22a53900895
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings; 18 19import com.android.internal.util.ArrayUtils; 20import com.android.settings.accounts.AccountSyncSettings; 21import com.android.settings.accounts.AuthenticatorHelper; 22import com.android.settings.accounts.ManageAccountsSettings; 23import com.android.settings.applications.ManageApplications; 24import com.android.settings.bluetooth.BluetoothEnabler; 25import com.android.settings.deviceinfo.Memory; 26import com.android.settings.fuelgauge.PowerUsageSummary; 27import com.android.settings.wifi.WifiEnabler; 28 29import android.accounts.Account; 30import android.accounts.AccountManager; 31import android.accounts.OnAccountsUpdateListener; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.content.pm.ActivityInfo; 36import android.content.pm.PackageManager; 37import android.content.pm.PackageManager.NameNotFoundException; 38import android.graphics.drawable.Drawable; 39import android.os.Bundle; 40import android.os.INetworkManagementService; 41import android.os.RemoteException; 42import android.os.ServiceManager; 43import android.os.UserId; 44import android.preference.Preference; 45import android.preference.PreferenceActivity; 46import android.preference.PreferenceActivity.Header; 47import android.preference.PreferenceFragment; 48import android.text.TextUtils; 49import android.util.Log; 50import android.view.LayoutInflater; 51import android.view.View; 52import android.view.View.OnClickListener; 53import android.view.ViewGroup; 54import android.widget.ArrayAdapter; 55import android.widget.Button; 56import android.widget.ImageView; 57import android.widget.ListAdapter; 58import android.widget.Switch; 59import android.widget.TextView; 60 61import java.util.ArrayList; 62import java.util.Collections; 63import java.util.Comparator; 64import java.util.HashMap; 65import java.util.List; 66 67/** 68 * Top-level settings activity to handle single pane and double pane UI layout. 69 */ 70public class Settings extends PreferenceActivity 71 implements ButtonBarHandler, OnAccountsUpdateListener { 72 73 private static final String LOG_TAG = "Settings"; 74 private static final String META_DATA_KEY_HEADER_ID = 75 "com.android.settings.TOP_LEVEL_HEADER_ID"; 76 private static final String META_DATA_KEY_FRAGMENT_CLASS = 77 "com.android.settings.FRAGMENT_CLASS"; 78 private static final String META_DATA_KEY_PARENT_TITLE = 79 "com.android.settings.PARENT_FRAGMENT_TITLE"; 80 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS = 81 "com.android.settings.PARENT_FRAGMENT_CLASS"; 82 83 private static final String EXTRA_CLEAR_UI_OPTIONS = "settings:remove_ui_options"; 84 85 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER"; 86 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER"; 87 88 private String mFragmentClass; 89 private int mTopLevelHeaderId; 90 private Header mFirstHeader; 91 private Header mCurrentHeader; 92 private Header mParentHeader; 93 private boolean mInLocalHeaderSwitch; 94 95 // Show only these settings for restricted users 96 private int[] SETTINGS_FOR_RESTRICTED = { 97 R.id.wifi_settings, 98 R.id.bluetooth_settings, 99 R.id.sound_settings, 100 R.id.display_settings, 101 R.id.security_settings, 102 R.id.account_settings, 103 R.id.about_settings 104 }; 105 106 private boolean mEnableUserManagement = false; 107 108 // TODO: Update Call Settings based on airplane mode state. 109 110 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>(); 111 private List<Header> mHeaders; 112 113 private AuthenticatorHelper mAuthenticatorHelper; 114 private Header mLastHeader; 115 private boolean mListeningToAccountUpdates; 116 117 @Override 118 protected void onCreate(Bundle savedInstanceState) { 119 if (getIntent().getBooleanExtra(EXTRA_CLEAR_UI_OPTIONS, false)) { 120 getWindow().setUiOptions(0); 121 } 122 123 if (android.provider.Settings.Secure.getInt(getContentResolver(), "multiuser_enabled", -1) 124 > 0) { 125 mEnableUserManagement = true; 126 } 127 128 mAuthenticatorHelper = new AuthenticatorHelper(); 129 mAuthenticatorHelper.updateAuthDescriptions(this); 130 mAuthenticatorHelper.onAccountsUpdated(this, null); 131 132 getMetaData(); 133 mInLocalHeaderSwitch = true; 134 super.onCreate(savedInstanceState); 135 mInLocalHeaderSwitch = false; 136 137 if (!onIsHidingHeaders() && onIsMultiPane()) { 138 highlightHeader(mTopLevelHeaderId); 139 // Force the title so that it doesn't get overridden by a direct launch of 140 // a specific settings screen. 141 setTitle(R.string.settings_label); 142 } 143 144 // Retrieve any saved state 145 if (savedInstanceState != null) { 146 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER); 147 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER); 148 } 149 150 // If the current header was saved, switch to it 151 if (savedInstanceState != null && mCurrentHeader != null) { 152 //switchToHeaderLocal(mCurrentHeader); 153 showBreadCrumbs(mCurrentHeader.title, null); 154 } 155 156 if (mParentHeader != null) { 157 setParentTitle(mParentHeader.title, null, new OnClickListener() { 158 public void onClick(View v) { 159 switchToParent(mParentHeader.fragment); 160 } 161 }); 162 } 163 164 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs 165 if (onIsMultiPane()) { 166 getActionBar().setDisplayHomeAsUpEnabled(false); 167 getActionBar().setHomeButtonEnabled(false); 168 } 169 } 170 171 @Override 172 protected void onSaveInstanceState(Bundle outState) { 173 super.onSaveInstanceState(outState); 174 175 // Save the current fragment, if it is the same as originally launched 176 if (mCurrentHeader != null) { 177 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader); 178 } 179 if (mParentHeader != null) { 180 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader); 181 } 182 } 183 184 @Override 185 public void onResume() { 186 super.onResume(); 187 188 ListAdapter listAdapter = getListAdapter(); 189 if (listAdapter instanceof HeaderAdapter) { 190 ((HeaderAdapter) listAdapter).resume(); 191 } 192 } 193 194 @Override 195 public void onPause() { 196 super.onPause(); 197 198 ListAdapter listAdapter = getListAdapter(); 199 if (listAdapter instanceof HeaderAdapter) { 200 ((HeaderAdapter) listAdapter).pause(); 201 } 202 } 203 204 @Override 205 public void onDestroy() { 206 super.onDestroy(); 207 if (mListeningToAccountUpdates) { 208 AccountManager.get(this).removeOnAccountsUpdatedListener(this); 209 } 210 } 211 212 private void switchToHeaderLocal(Header header) { 213 mInLocalHeaderSwitch = true; 214 switchToHeader(header); 215 mInLocalHeaderSwitch = false; 216 } 217 218 @Override 219 public void switchToHeader(Header header) { 220 if (!mInLocalHeaderSwitch) { 221 mCurrentHeader = null; 222 mParentHeader = null; 223 } 224 super.switchToHeader(header); 225 } 226 227 /** 228 * Switch to parent fragment and store the grand parent's info 229 * @param className name of the activity wrapper for the parent fragment. 230 */ 231 private void switchToParent(String className) { 232 final ComponentName cn = new ComponentName(this, className); 233 try { 234 final PackageManager pm = getPackageManager(); 235 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA); 236 237 if (parentInfo != null && parentInfo.metaData != null) { 238 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS); 239 CharSequence fragmentTitle = parentInfo.loadLabel(pm); 240 Header parentHeader = new Header(); 241 parentHeader.fragment = fragmentClass; 242 parentHeader.title = fragmentTitle; 243 mCurrentHeader = parentHeader; 244 245 switchToHeaderLocal(parentHeader); 246 highlightHeader(mTopLevelHeaderId); 247 248 mParentHeader = new Header(); 249 mParentHeader.fragment 250 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS); 251 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE); 252 } 253 } catch (NameNotFoundException nnfe) { 254 Log.w(LOG_TAG, "Could not find parent activity : " + className); 255 } 256 } 257 258 @Override 259 public void onNewIntent(Intent intent) { 260 super.onNewIntent(intent); 261 262 // If it is not launched from history, then reset to top-level 263 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0 264 && mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) { 265 switchToHeaderLocal(mFirstHeader); 266 } 267 } 268 269 private void highlightHeader(int id) { 270 if (id != 0) { 271 Integer index = mHeaderIndexMap.get(id); 272 if (index != null) { 273 getListView().setItemChecked(index, true); 274 getListView().smoothScrollToPosition(index); 275 } 276 } 277 } 278 279 @Override 280 public Intent getIntent() { 281 Intent superIntent = super.getIntent(); 282 String startingFragment = getStartingFragmentClass(superIntent); 283 // This is called from super.onCreate, isMultiPane() is not yet reliable 284 // Do not use onIsHidingHeaders either, which relies itself on this method 285 if (startingFragment != null && !onIsMultiPane()) { 286 Intent modIntent = new Intent(superIntent); 287 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment); 288 Bundle args = superIntent.getExtras(); 289 if (args != null) { 290 args = new Bundle(args); 291 } else { 292 args = new Bundle(); 293 } 294 args.putParcelable("intent", superIntent); 295 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras()); 296 return modIntent; 297 } 298 return superIntent; 299 } 300 301 /** 302 * Checks if the component name in the intent is different from the Settings class and 303 * returns the class name to load as a fragment. 304 */ 305 protected String getStartingFragmentClass(Intent intent) { 306 if (mFragmentClass != null) return mFragmentClass; 307 308 String intentClass = intent.getComponent().getClassName(); 309 if (intentClass.equals(getClass().getName())) return null; 310 311 if ("com.android.settings.ManageApplications".equals(intentClass) 312 || "com.android.settings.RunningServices".equals(intentClass) 313 || "com.android.settings.applications.StorageUse".equals(intentClass)) { 314 // Old names of manage apps. 315 intentClass = com.android.settings.applications.ManageApplications.class.getName(); 316 } 317 318 return intentClass; 319 } 320 321 /** 322 * Override initial header when an activity-alias is causing Settings to be launched 323 * for a specific fragment encoded in the android:name parameter. 324 */ 325 @Override 326 public Header onGetInitialHeader() { 327 String fragmentClass = getStartingFragmentClass(super.getIntent()); 328 if (fragmentClass != null) { 329 Header header = new Header(); 330 header.fragment = fragmentClass; 331 header.title = getTitle(); 332 header.fragmentArguments = getIntent().getExtras(); 333 mCurrentHeader = header; 334 return header; 335 } 336 337 return mFirstHeader; 338 } 339 340 @Override 341 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args, 342 int titleRes, int shortTitleRes) { 343 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args, 344 titleRes, shortTitleRes); 345 346 // some fragments want to avoid split actionbar 347 if (DataUsageSummary.class.getName().equals(fragmentName) || 348 PowerUsageSummary.class.getName().equals(fragmentName) || 349 AccountSyncSettings.class.getName().equals(fragmentName) || 350 UserDictionarySettings.class.getName().equals(fragmentName) || 351 Memory.class.getName().equals(fragmentName) || 352 ManageApplications.class.getName().equals(fragmentName) || 353 WirelessSettings.class.getName().equals(fragmentName) || 354 SoundSettings.class.getName().equals(fragmentName) || 355 PrivacySettings.class.getName().equals(fragmentName) || 356 ManageAccountsSettings.class.getName().equals(fragmentName)) { 357 intent.putExtra(EXTRA_CLEAR_UI_OPTIONS, true); 358 } 359 360 intent.setClass(this, SubSettings.class); 361 return intent; 362 } 363 364 /** 365 * Populate the activity with the top-level headers. 366 */ 367 @Override 368 public void onBuildHeaders(List<Header> headers) { 369 loadHeadersFromResource(R.xml.settings_headers, headers); 370 371 updateHeaderList(headers); 372 373 mHeaders = headers; 374 } 375 376 private void updateHeaderList(List<Header> target) { 377 int i = 0; 378 while (i < target.size()) { 379 Header header = target.get(i); 380 // Ids are integers, so downcasting 381 int id = (int) header.id; 382 if (id == R.id.dock_settings) { 383 if (!needsDockSettings()) 384 target.remove(header); 385 } else if (id == R.id.operator_settings || id == R.id.manufacturer_settings) { 386 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header); 387 } else if (id == R.id.wifi_settings) { 388 // Remove WiFi Settings if WiFi service is not available. 389 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) { 390 target.remove(header); 391 } 392 } else if (id == R.id.bluetooth_settings) { 393 // Remove Bluetooth Settings if Bluetooth service is not available. 394 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) { 395 target.remove(header); 396 } 397 } else if (id == R.id.data_usage_settings) { 398 // Remove data usage when kernel module not enabled 399 final INetworkManagementService netManager = INetworkManagementService.Stub 400 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)); 401 try { 402 if (!netManager.isBandwidthControlEnabled()) { 403 target.remove(header); 404 } 405 } catch (RemoteException e) { 406 // ignored 407 } 408 } else if (id == R.id.account_settings) { 409 int headerIndex = i + 1; 410 i = insertAccountsHeaders(target, headerIndex); 411 } else if (id == R.id.user_settings) { 412 if (!mEnableUserManagement 413 || !UserId.MU_ENABLED || UserId.myUserId() != 0 414 || !getResources().getBoolean(R.bool.enable_user_management) 415 || Utils.isMonkeyRunning()) { 416 target.remove(header); 417 } 418 } 419 if (UserId.MU_ENABLED && UserId.myUserId() != 0 420 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) { 421 target.remove(header); 422 } 423 424 // Increment if the current one wasn't removed by the Utils code. 425 if (target.get(i) == header) { 426 // Hold on to the first header, when we need to reset to the top-level 427 if (mFirstHeader == null && 428 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) { 429 mFirstHeader = header; 430 } 431 mHeaderIndexMap.put(id, i); 432 i++; 433 } 434 } 435 } 436 437 private int insertAccountsHeaders(List<Header> target, int headerIndex) { 438 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes(); 439 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length); 440 for (String accountType : accountTypes) { 441 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType); 442 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType); 443 boolean skipToAccount = accounts.length == 1 444 && !mAuthenticatorHelper.hasAccountPreferences(accountType); 445 Header accHeader = new Header(); 446 accHeader.title = label; 447 if (accHeader.extras == null) { 448 accHeader.extras = new Bundle(); 449 } 450 if (skipToAccount) { 451 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title; 452 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title; 453 accHeader.fragment = AccountSyncSettings.class.getName(); 454 accHeader.fragmentArguments = new Bundle(); 455 // Need this for the icon 456 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType); 457 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]); 458 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY, 459 accounts[0]); 460 } else { 461 accHeader.breadCrumbTitle = label; 462 accHeader.breadCrumbShortTitle = label; 463 accHeader.fragment = ManageAccountsSettings.class.getName(); 464 accHeader.fragmentArguments = new Bundle(); 465 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType); 466 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, 467 accountType); 468 if (!isMultiPane()) { 469 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL, 470 label.toString()); 471 } 472 } 473 accountHeaders.add(accHeader); 474 } 475 476 // Sort by label 477 Collections.sort(accountHeaders, new Comparator<Header>() { 478 @Override 479 public int compare(Header h1, Header h2) { 480 return h1.title.toString().compareTo(h2.title.toString()); 481 } 482 }); 483 484 for (Header header : accountHeaders) { 485 target.add(headerIndex++, header); 486 } 487 if (!mListeningToAccountUpdates) { 488 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true); 489 mListeningToAccountUpdates = true; 490 } 491 return headerIndex; 492 } 493 494 private boolean needsDockSettings() { 495 return getResources().getBoolean(R.bool.has_dock_settings); 496 } 497 498 private void getMetaData() { 499 try { 500 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(), 501 PackageManager.GET_META_DATA); 502 if (ai == null || ai.metaData == null) return; 503 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID); 504 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS); 505 506 // Check if it has a parent specified and create a Header object 507 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE); 508 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS); 509 if (parentFragmentClass != null) { 510 mParentHeader = new Header(); 511 mParentHeader.fragment = parentFragmentClass; 512 if (parentHeaderTitleRes != 0) { 513 mParentHeader.title = getResources().getString(parentHeaderTitleRes); 514 } 515 } 516 } catch (NameNotFoundException nnfe) { 517 // No recovery 518 } 519 } 520 521 @Override 522 public boolean hasNextButton() { 523 return super.hasNextButton(); 524 } 525 526 @Override 527 public Button getNextButton() { 528 return super.getNextButton(); 529 } 530 531 private static class HeaderAdapter extends ArrayAdapter<Header> { 532 static final int HEADER_TYPE_CATEGORY = 0; 533 static final int HEADER_TYPE_NORMAL = 1; 534 static final int HEADER_TYPE_SWITCH = 2; 535 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1; 536 537 private final WifiEnabler mWifiEnabler; 538 private final BluetoothEnabler mBluetoothEnabler; 539 private AuthenticatorHelper mAuthHelper; 540 541 private static class HeaderViewHolder { 542 ImageView icon; 543 TextView title; 544 TextView summary; 545 Switch switch_; 546 } 547 548 private LayoutInflater mInflater; 549 550 static int getHeaderType(Header header) { 551 if (header.fragment == null && header.intent == null) { 552 return HEADER_TYPE_CATEGORY; 553 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) { 554 return HEADER_TYPE_SWITCH; 555 } else { 556 return HEADER_TYPE_NORMAL; 557 } 558 } 559 560 @Override 561 public int getItemViewType(int position) { 562 Header header = getItem(position); 563 return getHeaderType(header); 564 } 565 566 @Override 567 public boolean areAllItemsEnabled() { 568 return false; // because of categories 569 } 570 571 @Override 572 public boolean isEnabled(int position) { 573 return getItemViewType(position) != HEADER_TYPE_CATEGORY; 574 } 575 576 @Override 577 public int getViewTypeCount() { 578 return HEADER_TYPE_COUNT; 579 } 580 581 @Override 582 public boolean hasStableIds() { 583 return true; 584 } 585 586 public HeaderAdapter(Context context, List<Header> objects, 587 AuthenticatorHelper authenticatorHelper) { 588 super(context, 0, objects); 589 590 mAuthHelper = authenticatorHelper; 591 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 592 593 // Temp Switches provided as placeholder until the adapter replaces these with actual 594 // Switches inflated from their layouts. Must be done before adapter is set in super 595 mWifiEnabler = new WifiEnabler(context, new Switch(context)); 596 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context)); 597 } 598 599 @Override 600 public View getView(int position, View convertView, ViewGroup parent) { 601 HeaderViewHolder holder; 602 Header header = getItem(position); 603 int headerType = getHeaderType(header); 604 View view = null; 605 606 if (convertView == null) { 607 holder = new HeaderViewHolder(); 608 switch (headerType) { 609 case HEADER_TYPE_CATEGORY: 610 view = new TextView(getContext(), null, 611 android.R.attr.listSeparatorTextViewStyle); 612 holder.title = (TextView) view; 613 break; 614 615 case HEADER_TYPE_SWITCH: 616 view = mInflater.inflate(R.layout.preference_header_switch_item, parent, 617 false); 618 holder.icon = (ImageView) view.findViewById(R.id.icon); 619 holder.title = (TextView) 620 view.findViewById(com.android.internal.R.id.title); 621 holder.summary = (TextView) 622 view.findViewById(com.android.internal.R.id.summary); 623 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget); 624 break; 625 626 case HEADER_TYPE_NORMAL: 627 view = mInflater.inflate( 628 R.layout.preference_header_item, parent, 629 false); 630 holder.icon = (ImageView) view.findViewById(R.id.icon); 631 holder.title = (TextView) 632 view.findViewById(com.android.internal.R.id.title); 633 holder.summary = (TextView) 634 view.findViewById(com.android.internal.R.id.summary); 635 break; 636 } 637 view.setTag(holder); 638 } else { 639 view = convertView; 640 holder = (HeaderViewHolder) view.getTag(); 641 } 642 643 // All view fields must be updated every time, because the view may be recycled 644 switch (headerType) { 645 case HEADER_TYPE_CATEGORY: 646 holder.title.setText(header.getTitle(getContext().getResources())); 647 break; 648 649 case HEADER_TYPE_SWITCH: 650 // Would need a different treatment if the main menu had more switches 651 if (header.id == R.id.wifi_settings) { 652 mWifiEnabler.setSwitch(holder.switch_); 653 } else { 654 mBluetoothEnabler.setSwitch(holder.switch_); 655 } 656 // No break, fall through on purpose to update common fields 657 658 //$FALL-THROUGH$ 659 case HEADER_TYPE_NORMAL: 660 if (header.extras != null 661 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) { 662 String accType = header.extras.getString( 663 ManageAccountsSettings.KEY_ACCOUNT_TYPE); 664 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams(); 665 lp.width = getContext().getResources().getDimensionPixelSize( 666 R.dimen.header_icon_width); 667 lp.height = lp.width; 668 holder.icon.setLayoutParams(lp); 669 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType); 670 holder.icon.setImageDrawable(icon); 671 } else { 672 holder.icon.setImageResource(header.iconRes); 673 } 674 holder.title.setText(header.getTitle(getContext().getResources())); 675 CharSequence summary = header.getSummary(getContext().getResources()); 676 if (!TextUtils.isEmpty(summary)) { 677 holder.summary.setVisibility(View.VISIBLE); 678 holder.summary.setText(summary); 679 } else { 680 holder.summary.setVisibility(View.GONE); 681 } 682 break; 683 } 684 685 return view; 686 } 687 688 public void resume() { 689 mWifiEnabler.resume(); 690 mBluetoothEnabler.resume(); 691 } 692 693 public void pause() { 694 mWifiEnabler.pause(); 695 mBluetoothEnabler.pause(); 696 } 697 } 698 699 @Override 700 public void onHeaderClick(Header header, int position) { 701 boolean revert = false; 702 if (header.id == R.id.account_add) { 703 revert = true; 704 } 705 706 super.onHeaderClick(header, position); 707 708 if (revert && mLastHeader != null) { 709 highlightHeader((int) mLastHeader.id); 710 } else { 711 mLastHeader = header; 712 } 713 } 714 715 @Override 716 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { 717 // Override the fragment title for Wallpaper settings 718 int titleRes = pref.getTitleRes(); 719 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) { 720 titleRes = R.string.wallpaper_settings_fragment_title; 721 } 722 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(), 723 null, 0); 724 return true; 725 } 726 727 public boolean shouldUpRecreateTask(Intent targetIntent) { 728 return super.shouldUpRecreateTask(new Intent(this, Settings.class)); 729 } 730 731 @Override 732 public void setListAdapter(ListAdapter adapter) { 733 if (mHeaders == null) { 734 mHeaders = new ArrayList<Header>(); 735 // When the saved state provides the list of headers, onBuildHeaders is not called 736 // Copy the list of Headers from the adapter, preserving their order 737 for (int i = 0; i < adapter.getCount(); i++) { 738 mHeaders.add((Header) adapter.getItem(i)); 739 } 740 } 741 742 // Ignore the adapter provided by PreferenceActivity and substitute ours instead 743 super.setListAdapter(new HeaderAdapter(this, mHeaders, mAuthenticatorHelper)); 744 } 745 746 @Override 747 public void onAccountsUpdated(Account[] accounts) { 748 mAuthenticatorHelper.onAccountsUpdated(this, accounts); 749 invalidateHeaders(); 750 } 751 752 /* 753 * Settings subclasses for launching independently. 754 */ 755 public static class BluetoothSettingsActivity extends Settings { /* empty */ } 756 public static class WirelessSettingsActivity extends Settings { /* empty */ } 757 public static class TetherSettingsActivity extends Settings { /* empty */ } 758 public static class VpnSettingsActivity extends Settings { /* empty */ } 759 public static class DateTimeSettingsActivity extends Settings { /* empty */ } 760 public static class StorageSettingsActivity extends Settings { /* empty */ } 761 public static class WifiSettingsActivity extends Settings { /* empty */ } 762 public static class WifiP2pSettingsActivity extends Settings { /* empty */ } 763 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ } 764 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ } 765 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ } 766 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ } 767 public static class LocalePickerActivity extends Settings { /* empty */ } 768 public static class UserDictionarySettingsActivity extends Settings { /* empty */ } 769 public static class SoundSettingsActivity extends Settings { /* empty */ } 770 public static class DisplaySettingsActivity extends Settings { /* empty */ } 771 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ } 772 public static class ApplicationSettingsActivity extends Settings { /* empty */ } 773 public static class ManageApplicationsActivity extends Settings { /* empty */ } 774 public static class StorageUseActivity extends Settings { /* empty */ } 775 public static class DevelopmentSettingsActivity extends Settings { /* empty */ } 776 public static class AccessibilitySettingsActivity extends Settings { /* empty */ } 777 public static class SecuritySettingsActivity extends Settings { /* empty */ } 778 public static class LocationSettingsActivity extends Settings { /* empty */ } 779 public static class PrivacySettingsActivity extends Settings { /* empty */ } 780 public static class DockSettingsActivity extends Settings { /* empty */ } 781 public static class RunningServicesActivity extends Settings { /* empty */ } 782 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ } 783 public static class PowerUsageSummaryActivity extends Settings { /* empty */ } 784 public static class AccountSyncSettingsActivity extends Settings { /* empty */ } 785 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ } 786 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ } 787 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ } 788 public static class DataUsageSummaryActivity extends Settings { /* empty */ } 789 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ } 790 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ } 791 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ } 792} 793