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