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