blob: e754f986d39f58dd8e91874d3a61c3e5bd28b4cb [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
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
Amith Yamasani56821db2012-06-05 13:20:45 -070019import android.accounts.Account;
20import android.accounts.AccountManager;
21import android.accounts.OnAccountsUpdateListener;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090022import android.content.BroadcastReceiver;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080023import android.content.ComponentName;
Gilles Debunnee78c1872011-06-20 15:00:07 -070024import android.content.Context;
Amith Yamasani379d9b02010-09-27 12:03:59 -070025import android.content.Intent;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090026import android.content.IntentFilter;
Dianne Hackborncaefa9b2012-10-10 15:05:42 -070027import android.content.SharedPreferences;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070028import android.content.pm.ActivityInfo;
29import android.content.pm.PackageManager;
30import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070031import android.graphics.drawable.Drawable;
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -070032import android.os.Bundle;
Jeff Sharkey34e964d2012-04-21 15:41:48 -070033import android.os.INetworkManagementService;
34import android.os.RemoteException;
35import android.os.ServiceManager;
Dianne Hackbornbb06a422012-08-16 11:01:57 -070036import android.os.UserHandle;
Jeff Sharkey44202462012-09-19 13:13:45 -070037import android.os.UserManager;
Amith Yamasania4379d62011-07-22 10:34:58 -070038import android.preference.Preference;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070039import android.preference.PreferenceActivity;
Amith Yamasania4379d62011-07-22 10:34:58 -070040import android.preference.PreferenceFragment;
Gilles Debunnee78c1872011-06-20 15:00:07 -070041import android.text.TextUtils;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080042import android.util.Log;
Gilles Debunnee78c1872011-06-20 15:00:07 -070043import android.view.LayoutInflater;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080044import android.view.View;
45import android.view.View.OnClickListener;
Gilles Debunnee78c1872011-06-20 15:00:07 -070046import android.view.ViewGroup;
47import android.widget.ArrayAdapter;
Amith Yamasani9e3a4702011-01-11 09:09:26 -080048import android.widget.Button;
Gilles Debunnee78c1872011-06-20 15:00:07 -070049import android.widget.ImageView;
50import android.widget.ListAdapter;
51import android.widget.Switch;
52import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080053
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080054import com.android.internal.util.ArrayUtils;
Amith Yamasania677ee22013-07-26 13:38:41 -070055import com.android.settings.accessibility.AccessibilitySettings;
Alan Viverette341ff662013-07-18 17:49:33 -070056import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
Alan Viverette9b625f02013-09-11 13:03:14 -070057import com.android.settings.accessibility.ToggleCaptioningPreferenceFragment;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080058import com.android.settings.accounts.AccountSyncSettings;
59import com.android.settings.accounts.AuthenticatorHelper;
60import com.android.settings.accounts.ManageAccountsSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070061import com.android.settings.applications.AppOpsSummary;
62import com.android.settings.applications.ManageApplications;
Dianne Hackbornc6d658e2013-08-08 12:57:53 -070063import com.android.settings.applications.ProcessStatsUi;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080064import com.android.settings.bluetooth.BluetoothEnabler;
65import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070066import com.android.settings.deviceinfo.Memory;
67import com.android.settings.deviceinfo.UsbSettings;
68import com.android.settings.fuelgauge.PowerUsageSummary;
69import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
Amith Yamasani3a14ae22013-08-30 15:43:44 -070070import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070071import com.android.settings.inputmethod.SpellCheckersSettings;
72import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070073import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070074import com.android.settings.nfc.AndroidBeam;
Martijn Coenen53083ab2013-08-09 13:37:38 -070075import com.android.settings.nfc.PaymentSettings;
Svetoslav2d531652013-09-03 21:32:40 -070076import com.android.settings.print.PrintServiceSettingsFragment;
77import com.android.settings.print.PrintSettingsFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070078import com.android.settings.tts.TextToSpeechSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070079import com.android.settings.users.UserSettings;
80import com.android.settings.vpn2.VpnSettings;
Jeff Sharkey0c3634c2013-02-20 12:35:16 -080081import com.android.settings.wfd.WifiDisplaySettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070082import com.android.settings.wifi.AdvancedWifiSettings;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080083import com.android.settings.wifi.WifiEnabler;
84import com.android.settings.wifi.WifiSettings;
85import com.android.settings.wifi.p2p.WifiP2pSettings;
86
Gilles Debunnee78c1872011-06-20 15:00:07 -070087import java.util.ArrayList;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070088import java.util.Collections;
89import java.util.Comparator;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070090import java.util.HashMap;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070091import java.util.List;
Amith Yamasanid7993472010-08-18 13:59:28 -070092
93/**
94 * Top-level settings activity to handle single pane and double pane UI layout.
95 */
Amith Yamasani56821db2012-06-05 13:20:45 -070096public class Settings extends PreferenceActivity
97 implements ButtonBarHandler, OnAccountsUpdateListener {
Amith Yamasanid7993472010-08-18 13:59:28 -070098
Gilles Debunnee78c1872011-06-20 15:00:07 -070099 private static final String LOG_TAG = "Settings";
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700100
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700101 private static final String META_DATA_KEY_HEADER_ID =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700102 "com.android.settings.TOP_LEVEL_HEADER_ID";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700103 private static final String META_DATA_KEY_FRAGMENT_CLASS =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700104 "com.android.settings.FRAGMENT_CLASS";
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800105 private static final String META_DATA_KEY_PARENT_TITLE =
106 "com.android.settings.PARENT_FRAGMENT_TITLE";
107 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
108 "com.android.settings.PARENT_FRAGMENT_CLASS";
109
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800110 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700111
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800112 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
113 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700114
115 private String mFragmentClass;
116 private int mTopLevelHeaderId;
Amith Yamasani3965ae62010-11-15 14:45:19 -0800117 private Header mFirstHeader;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800118 private Header mCurrentHeader;
119 private Header mParentHeader;
120 private boolean mInLocalHeaderSwitch;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700121
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700122 // Show only these settings for restricted users
123 private int[] SETTINGS_FOR_RESTRICTED = {
Amith Yamasani32630392012-08-10 19:31:39 -0700124 R.id.wireless_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700125 R.id.wifi_settings,
126 R.id.bluetooth_settings,
Jeff Sharkey38305fb2012-09-14 16:26:51 -0700127 R.id.data_usage_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700128 R.id.wireless_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700129 R.id.device_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700130 R.id.sound_settings,
131 R.id.display_settings,
Jeff Sharkey90c8b202012-08-30 15:20:10 -0700132 R.id.storage_settings,
Dianne Hackborn271c8b02012-08-20 17:24:39 -0700133 R.id.application_settings,
Dianne Hackborn52e56a22012-09-12 17:02:23 -0700134 R.id.battery_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700135 R.id.personal_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700136 R.id.location_settings,
Amith Yamasani3deeeb72012-04-05 14:44:48 -0700137 R.id.security_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700138 R.id.language_settings,
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700139 R.id.user_settings,
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700140 R.id.account_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700141 R.id.account_add,
142 R.id.system_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700143 R.id.date_time_settings,
Jeff Brown9e143f52012-09-19 20:46:07 -0700144 R.id.about_settings,
Svetoslav Ganovd4c7b492013-06-11 21:15:11 -0700145 R.id.accessibility_settings,
Martijn Coenen26515da2013-08-01 18:13:33 -0700146 R.id.print_settings,
147 R.id.nfc_payment_settings
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700148 };
149
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700150 private SharedPreferences mDevelopmentPreferences;
151 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
152
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700153 // TODO: Update Call Settings based on airplane mode state.
Amith Yamasanib61cf512010-09-12 08:17:50 -0700154
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700155 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
156
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700157 private AuthenticatorHelper mAuthenticatorHelper;
158 private Header mLastHeader;
Amith Yamasani86708a82012-06-06 20:23:08 -0700159 private boolean mListeningToAccountUpdates;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700160
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900161 private boolean mBatteryPresent = true;
162 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
163
164 @Override
165 public void onReceive(Context context, Intent intent) {
166 String action = intent.getAction();
167 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
168 boolean batteryPresent = Utils.isBatteryPresent(intent);
169
170 if (mBatteryPresent != batteryPresent) {
171 mBatteryPresent = batteryPresent;
172 invalidateHeaders();
173 }
174 }
175 }
176 };
177
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700178 @Override
179 protected void onCreate(Bundle savedInstanceState) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800180 if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
181 getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
Jeff Sharkey54d0af52011-08-11 18:26:57 -0700182 }
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700183
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700184 mAuthenticatorHelper = new AuthenticatorHelper();
185 mAuthenticatorHelper.updateAuthDescriptions(this);
186 mAuthenticatorHelper.onAccountsUpdated(this, null);
187
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700188 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
189 Context.MODE_PRIVATE);
190
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700191 getMetaData();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800192 mInLocalHeaderSwitch = true;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700193 super.onCreate(savedInstanceState);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800194 mInLocalHeaderSwitch = false;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700195
Gilles Debunne3661b622011-06-27 11:19:16 -0700196 if (!onIsHidingHeaders() && onIsMultiPane()) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700197 highlightHeader(mTopLevelHeaderId);
Amith Yamasani72aa19d2010-12-09 06:07:12 -0800198 // Force the title so that it doesn't get overridden by a direct launch of
199 // a specific settings screen.
200 setTitle(R.string.settings_label);
201 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800202
203 // Retrieve any saved state
204 if (savedInstanceState != null) {
205 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
206 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
207 }
208
209 // If the current header was saved, switch to it
210 if (savedInstanceState != null && mCurrentHeader != null) {
211 //switchToHeaderLocal(mCurrentHeader);
212 showBreadCrumbs(mCurrentHeader.title, null);
213 }
214
215 if (mParentHeader != null) {
216 setParentTitle(mParentHeader.title, null, new OnClickListener() {
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400217 @Override
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800218 public void onClick(View v) {
219 switchToParent(mParentHeader.fragment);
220 }
221 });
222 }
Gilles Debunnedc7101f2011-06-27 12:00:49 -0700223
Amith Yamasani3d384f42012-05-11 15:22:04 -0700224 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
225 if (onIsMultiPane()) {
226 getActionBar().setDisplayHomeAsUpEnabled(false);
227 getActionBar().setHomeButtonEnabled(false);
228 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800229 }
230
231 @Override
232 protected void onSaveInstanceState(Bundle outState) {
233 super.onSaveInstanceState(outState);
234
235 // Save the current fragment, if it is the same as originally launched
236 if (mCurrentHeader != null) {
237 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
238 }
239 if (mParentHeader != null) {
240 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
241 }
242 }
243
Gilles Debunnee78c1872011-06-20 15:00:07 -0700244 @Override
245 public void onResume() {
246 super.onResume();
247
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700248 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
249 @Override
250 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
251 invalidateHeaders();
252 }
253 };
254 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
255 mDevelopmentPreferencesListener);
256
Gilles Debunnee78c1872011-06-20 15:00:07 -0700257 ListAdapter listAdapter = getListAdapter();
258 if (listAdapter instanceof HeaderAdapter) {
259 ((HeaderAdapter) listAdapter).resume();
260 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700261 invalidateHeaders();
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900262
263 registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700264 }
265
266 @Override
267 public void onPause() {
268 super.onPause();
269
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900270 unregisterReceiver(mBatteryInfoReceiver);
271
Gilles Debunnee78c1872011-06-20 15:00:07 -0700272 ListAdapter listAdapter = getListAdapter();
273 if (listAdapter instanceof HeaderAdapter) {
274 ((HeaderAdapter) listAdapter).pause();
Amith Yamasani86708a82012-06-06 20:23:08 -0700275 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700276
277 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
278 mDevelopmentPreferencesListener);
279 mDevelopmentPreferencesListener = null;
Amith Yamasani86708a82012-06-06 20:23:08 -0700280 }
281
282 @Override
283 public void onDestroy() {
284 super.onDestroy();
285 if (mListeningToAccountUpdates) {
Amith Yamasani56821db2012-06-05 13:20:45 -0700286 AccountManager.get(this).removeOnAccountsUpdatedListener(this);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700287 }
288 }
289
Amith Yamasani56f51a82013-08-05 10:07:23 -0700290 @Override
291 public boolean onIsMultiPane() {
292 return false;
293 }
294
Amith Yamasania677ee22013-07-26 13:38:41 -0700295 private static final String[] ENTRY_FRAGMENTS = {
296 WirelessSettings.class.getName(),
297 WifiSettings.class.getName(),
298 AdvancedWifiSettings.class.getName(),
299 BluetoothSettings.class.getName(),
300 TetherSettings.class.getName(),
301 WifiP2pSettings.class.getName(),
302 VpnSettings.class.getName(),
303 DateTimeSettings.class.getName(),
304 LocalePicker.class.getName(),
305 InputMethodAndLanguageSettings.class.getName(),
306 SpellCheckersSettings.class.getName(),
307 UserDictionaryList.class.getName(),
308 UserDictionarySettings.class.getName(),
309 SoundSettings.class.getName(),
310 DisplaySettings.class.getName(),
311 DeviceInfoSettings.class.getName(),
312 ManageApplications.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700313 ProcessStatsUi.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700314 NotificationStation.class.getName(),
315 AppOpsSummary.class.getName(),
316 LocationSettings.class.getName(),
317 SecuritySettings.class.getName(),
318 PrivacySettings.class.getName(),
319 DeviceAdminSettings.class.getName(),
320 AccessibilitySettings.class.getName(),
Alan Viverette9b625f02013-09-11 13:03:14 -0700321 ToggleCaptioningPreferenceFragment.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700322 TextToSpeechSettings.class.getName(),
323 Memory.class.getName(),
324 DevelopmentSettings.class.getName(),
325 UsbSettings.class.getName(),
326 AndroidBeam.class.getName(),
327 WifiDisplaySettings.class.getName(),
328 PowerUsageSummary.class.getName(),
329 AccountSyncSettings.class.getName(),
330 CryptKeeperSettings.class.getName(),
331 DataUsageSummary.class.getName(),
332 DreamSettings.class.getName(),
333 UserSettings.class.getName(),
334 NotificationAccessSettings.class.getName(),
Amith Yamasaniee226f92013-08-05 11:02:16 -0700335 ManageAccountsSettings.class.getName(),
Svetoslav2d531652013-09-03 21:32:40 -0700336 PrintSettingsFragment.class.getName(),
Martijn Coenen53083ab2013-08-09 13:37:38 -0700337 TrustedCredentialsSettings.class.getName(),
Amith Yamasani3a14ae22013-08-30 15:43:44 -0700338 PaymentSettings.class.getName(),
339 KeyboardLayoutPickerFragment.class.getName()
Amith Yamasania677ee22013-07-26 13:38:41 -0700340 };
341
342 @Override
343 protected boolean isValidFragment(String fragmentName) {
344 // Almost all fragments are wrapped in this,
345 // except for a few that have their own activities.
346 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
347 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
348 }
349 return false;
350 }
351
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800352 private void switchToHeaderLocal(Header header) {
353 mInLocalHeaderSwitch = true;
354 switchToHeader(header);
355 mInLocalHeaderSwitch = false;
356 }
357
358 @Override
359 public void switchToHeader(Header header) {
360 if (!mInLocalHeaderSwitch) {
361 mCurrentHeader = null;
362 mParentHeader = null;
363 }
364 super.switchToHeader(header);
365 }
366
367 /**
368 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800369 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800370 */
371 private void switchToParent(String className) {
372 final ComponentName cn = new ComponentName(this, className);
373 try {
374 final PackageManager pm = getPackageManager();
375 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
376
377 if (parentInfo != null && parentInfo.metaData != null) {
378 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
379 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
380 Header parentHeader = new Header();
381 parentHeader.fragment = fragmentClass;
382 parentHeader.title = fragmentTitle;
383 mCurrentHeader = parentHeader;
384
385 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700386 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800387
388 mParentHeader = new Header();
389 mParentHeader.fragment
390 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
391 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
392 }
393 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700394 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800395 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700396 }
397
Amith Yamasani3965ae62010-11-15 14:45:19 -0800398 @Override
399 public void onNewIntent(Intent intent) {
400 super.onNewIntent(intent);
401
402 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700403 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
404 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
405 switchToHeaderLocal(mFirstHeader);
406 }
407 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800408 }
409 }
410
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700411 private void highlightHeader(int id) {
412 if (id != 0) {
413 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700414 if (index != null) {
415 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700416 if (isMultiPane()) {
417 getListView().smoothScrollToPosition(index);
418 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700419 }
420 }
421 }
422
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700423 @Override
424 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700425 Intent superIntent = super.getIntent();
426 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700427 // This is called from super.onCreate, isMultiPane() is not yet reliable
428 // Do not use onIsHidingHeaders either, which relies itself on this method
429 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700430 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700431 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700432 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700433 if (args != null) {
434 args = new Bundle(args);
435 } else {
436 args = new Bundle();
437 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700438 args.putParcelable("intent", superIntent);
439 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700440 return modIntent;
441 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700442 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700443 }
444
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700445 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700446 * Checks if the component name in the intent is different from the Settings class and
447 * returns the class name to load as a fragment.
448 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700449 protected String getStartingFragmentClass(Intent intent) {
450 if (mFragmentClass != null) return mFragmentClass;
451
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700452 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700453 if (intentClass.equals(getClass().getName())) return null;
454
Dianne Hackbornee293792010-11-01 12:32:33 -0700455 if ("com.android.settings.ManageApplications".equals(intentClass)
456 || "com.android.settings.RunningServices".equals(intentClass)
457 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700458 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700459 intentClass = com.android.settings.applications.ManageApplications.class.getName();
460 }
461
Amith Yamasani379d9b02010-09-27 12:03:59 -0700462 return intentClass;
463 }
464
465 /**
466 * Override initial header when an activity-alias is causing Settings to be launched
467 * for a specific fragment encoded in the android:name parameter.
468 */
469 @Override
470 public Header onGetInitialHeader() {
471 String fragmentClass = getStartingFragmentClass(super.getIntent());
472 if (fragmentClass != null) {
473 Header header = new Header();
474 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800475 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700476 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800477 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700478 return header;
479 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700480
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700481 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700482 }
483
Dianne Hackbornb7258182011-03-15 16:23:55 -0700484 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700485 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
486 int titleRes, int shortTitleRes) {
487 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
488 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700489
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800490 // Some fragments want split ActionBar; these should stay in sync with
491 // uiOptions for fragments also defined as activities in manifest.
492 if (WifiSettings.class.getName().equals(fragmentName) ||
493 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800494 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800495 BluetoothSettings.class.getName().equals(fragmentName) ||
496 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700497 LocationSettings.class.getName().equals(fragmentName) ||
Svetoslav2d531652013-09-03 21:32:40 -0700498 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName) ||
499 PrintSettingsFragment.class.getName().equals(fragmentName) ||
500 PrintServiceSettingsFragment.class.getName().equals(fragmentName)) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800501 intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700502 }
503
Dianne Hackbornb7258182011-03-15 16:23:55 -0700504 intent.setClass(this, SubSettings.class);
505 return intent;
506 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700507
Amith Yamasani379d9b02010-09-27 12:03:59 -0700508 /**
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700509 * Populate the activity with the top-level headers.
510 */
Amith Yamasanid7993472010-08-18 13:59:28 -0700511 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700512 public void onBuildHeaders(List<Header> headers) {
513 loadHeadersFromResource(R.xml.settings_headers, headers);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700514 updateHeaderList(headers);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700515 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700516
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700517 private void updateHeaderList(List<Header> target) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700518 final boolean showDev = mDevelopmentPreferences.getBoolean(
519 DevelopmentSettings.PREF_SHOW,
520 android.os.Build.TYPE.equals("eng"));
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700521 int i = 0;
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400522
523 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700524 mHeaderIndexMap.clear();
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700525 while (i < target.size()) {
526 Header header = target.get(i);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700527 // Ids are integers, so downcasting
528 int id = (int) header.id;
Chris Wren2bc32ae2012-09-24 14:23:46 -0400529 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700530 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
Gilles Debunne2454f492011-06-21 16:16:06 -0700531 } else if (id == R.id.wifi_settings) {
532 // Remove WiFi Settings if WiFi service is not available.
533 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700534 target.remove(i);
Gilles Debunne2454f492011-06-21 16:16:06 -0700535 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700536 } else if (id == R.id.bluetooth_settings) {
537 // Remove Bluetooth Settings if Bluetooth service is not available.
Gilles Debunne2454f492011-06-21 16:16:06 -0700538 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700539 target.remove(i);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700540 }
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700541 } else if (id == R.id.data_usage_settings) {
542 // Remove data usage when kernel module not enabled
543 final INetworkManagementService netManager = INetworkManagementService.Stub
544 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
545 try {
546 if (!netManager.isBandwidthControlEnabled()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700547 target.remove(i);
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700548 }
549 } catch (RemoteException e) {
550 // ignored
551 }
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900552 } else if (id == R.id.battery_settings) {
553 // Remove battery settings when battery is not available. (e.g. TV)
554
555 if (!mBatteryPresent) {
556 target.remove(i);
557 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700558 } else if (id == R.id.account_settings) {
559 int headerIndex = i + 1;
560 i = insertAccountsHeaders(target, headerIndex);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700561 } else if (id == R.id.user_settings) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700562 if (!UserHandle.MU_ENABLED
Jeff Sharkey44202462012-09-19 13:13:45 -0700563 || !UserManager.supportsMultipleUsers()
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700564 || Utils.isMonkeyRunning()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700565 target.remove(i);
566 }
Martijn Coenen26515da2013-08-01 18:13:33 -0700567 } else if (id == R.id.nfc_payment_settings) {
568 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
569 target.remove(i);
570 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700571 } else if (id == R.id.development_settings) {
572 if (!showDev) {
573 target.remove(i);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700574 }
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400575 } else if (id == R.id.account_add) {
576 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
577 target.remove(i);
578 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700579 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700580
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900581 if (i < target.size() && target.get(i) == header
Amith Yamasanib99f8642012-10-10 21:41:12 -0700582 && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700583 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700584 target.remove(i);
Amith Yamasanid7993472010-08-18 13:59:28 -0700585 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700586
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700587 // Increment if the current one wasn't removed by the Utils code.
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900588 if (i < target.size() && target.get(i) == header) {
Amith Yamasani3965ae62010-11-15 14:45:19 -0800589 // Hold on to the first header, when we need to reset to the top-level
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700590 if (mFirstHeader == null &&
591 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
592 mFirstHeader = header;
593 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700594 mHeaderIndexMap.put(id, i);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700595 i++;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700596 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700597 }
598 }
599
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700600 private int insertAccountsHeaders(List<Header> target, int headerIndex) {
601 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
602 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
603 for (String accountType : accountTypes) {
604 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
Brian Muramatsuc28af522012-06-28 14:25:14 -0700605 if (label == null) {
606 continue;
607 }
608
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700609 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
610 boolean skipToAccount = accounts.length == 1
611 && !mAuthenticatorHelper.hasAccountPreferences(accountType);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700612 Header accHeader = new Header();
613 accHeader.title = label;
614 if (accHeader.extras == null) {
615 accHeader.extras = new Bundle();
616 }
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700617 if (skipToAccount) {
618 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
619 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
620 accHeader.fragment = AccountSyncSettings.class.getName();
621 accHeader.fragmentArguments = new Bundle();
622 // Need this for the icon
623 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
624 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
625 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
626 accounts[0]);
627 } else {
628 accHeader.breadCrumbTitle = label;
629 accHeader.breadCrumbShortTitle = label;
630 accHeader.fragment = ManageAccountsSettings.class.getName();
631 accHeader.fragmentArguments = new Bundle();
632 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
633 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
634 accountType);
635 if (!isMultiPane()) {
636 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
637 label.toString());
638 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700639 }
640 accountHeaders.add(accHeader);
641 }
642
643 // Sort by label
644 Collections.sort(accountHeaders, new Comparator<Header>() {
645 @Override
646 public int compare(Header h1, Header h2) {
647 return h1.title.toString().compareTo(h2.title.toString());
648 }
649 });
650
651 for (Header header : accountHeaders) {
652 target.add(headerIndex++, header);
653 }
Amith Yamasani86708a82012-06-06 20:23:08 -0700654 if (!mListeningToAccountUpdates) {
655 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
656 mListeningToAccountUpdates = true;
657 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700658 return headerIndex;
659 }
660
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700661 private void getMetaData() {
662 try {
663 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
664 PackageManager.GET_META_DATA);
665 if (ai == null || ai.metaData == null) return;
666 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
667 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700668
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800669 // Check if it has a parent specified and create a Header object
670 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
671 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
672 if (parentFragmentClass != null) {
673 mParentHeader = new Header();
674 mParentHeader.fragment = parentFragmentClass;
675 if (parentHeaderTitleRes != 0) {
676 mParentHeader.title = getResources().getString(parentHeaderTitleRes);
677 }
678 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700679 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700680 // No recovery
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700681 }
682 }
683
Amith Yamasani9e3a4702011-01-11 09:09:26 -0800684 @Override
685 public boolean hasNextButton() {
686 return super.hasNextButton();
687 }
688
689 @Override
690 public Button getNextButton() {
691 return super.getNextButton();
692 }
693
Gilles Debunnee78c1872011-06-20 15:00:07 -0700694 private static class HeaderAdapter extends ArrayAdapter<Header> {
695 static final int HEADER_TYPE_CATEGORY = 0;
696 static final int HEADER_TYPE_NORMAL = 1;
697 static final int HEADER_TYPE_SWITCH = 2;
698 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
699
700 private final WifiEnabler mWifiEnabler;
701 private final BluetoothEnabler mBluetoothEnabler;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700702 private AuthenticatorHelper mAuthHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700703
704 private static class HeaderViewHolder {
705 ImageView icon;
706 TextView title;
707 TextView summary;
708 Switch switch_;
709 }
710
711 private LayoutInflater mInflater;
712
713 static int getHeaderType(Header header) {
714 if (header.fragment == null && header.intent == null) {
715 return HEADER_TYPE_CATEGORY;
716 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
717 return HEADER_TYPE_SWITCH;
718 } else {
719 return HEADER_TYPE_NORMAL;
720 }
721 }
722
723 @Override
724 public int getItemViewType(int position) {
725 Header header = getItem(position);
726 return getHeaderType(header);
727 }
728
729 @Override
730 public boolean areAllItemsEnabled() {
731 return false; // because of categories
732 }
733
734 @Override
735 public boolean isEnabled(int position) {
736 return getItemViewType(position) != HEADER_TYPE_CATEGORY;
737 }
738
739 @Override
740 public int getViewTypeCount() {
741 return HEADER_TYPE_COUNT;
742 }
743
744 @Override
745 public boolean hasStableIds() {
746 return true;
747 }
748
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700749 public HeaderAdapter(Context context, List<Header> objects,
750 AuthenticatorHelper authenticatorHelper) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700751 super(context, 0, objects);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700752
753 mAuthHelper = authenticatorHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700754 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700755
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700756 // Temp Switches provided as placeholder until the adapter replaces these with actual
Gilles Debunnee78c1872011-06-20 15:00:07 -0700757 // Switches inflated from their layouts. Must be done before adapter is set in super
758 mWifiEnabler = new WifiEnabler(context, new Switch(context));
759 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
760 }
761
762 @Override
763 public View getView(int position, View convertView, ViewGroup parent) {
764 HeaderViewHolder holder;
765 Header header = getItem(position);
766 int headerType = getHeaderType(header);
767 View view = null;
768
769 if (convertView == null) {
770 holder = new HeaderViewHolder();
771 switch (headerType) {
772 case HEADER_TYPE_CATEGORY:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700773 view = new TextView(getContext(), null,
774 android.R.attr.listSeparatorTextViewStyle);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700775 holder.title = (TextView) view;
776 break;
777
778 case HEADER_TYPE_SWITCH:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700779 view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
780 false);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700781 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700782 holder.title = (TextView)
783 view.findViewById(com.android.internal.R.id.title);
784 holder.summary = (TextView)
785 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700786 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
787 break;
788
789 case HEADER_TYPE_NORMAL:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700790 view = mInflater.inflate(
Amith Yamasanic8a93172012-06-08 13:35:47 -0700791 R.layout.preference_header_item, parent,
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700792 false);
Amith Yamasanic8a93172012-06-08 13:35:47 -0700793 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700794 holder.title = (TextView)
795 view.findViewById(com.android.internal.R.id.title);
796 holder.summary = (TextView)
797 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700798 break;
799 }
800 view.setTag(holder);
801 } else {
802 view = convertView;
803 holder = (HeaderViewHolder) view.getTag();
804 }
805
806 // All view fields must be updated every time, because the view may be recycled
807 switch (headerType) {
808 case HEADER_TYPE_CATEGORY:
809 holder.title.setText(header.getTitle(getContext().getResources()));
810 break;
811
812 case HEADER_TYPE_SWITCH:
813 // Would need a different treatment if the main menu had more switches
814 if (header.id == R.id.wifi_settings) {
815 mWifiEnabler.setSwitch(holder.switch_);
816 } else {
817 mBluetoothEnabler.setSwitch(holder.switch_);
818 }
819 // No break, fall through on purpose to update common fields
820
821 //$FALL-THROUGH$
822 case HEADER_TYPE_NORMAL:
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700823 if (header.extras != null
824 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700825 String accType = header.extras.getString(
826 ManageAccountsSettings.KEY_ACCOUNT_TYPE);
827 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
828 lp.width = getContext().getResources().getDimensionPixelSize(
829 R.dimen.header_icon_width);
830 lp.height = lp.width;
831 holder.icon.setLayoutParams(lp);
832 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
833 holder.icon.setImageDrawable(icon);
834 } else {
835 holder.icon.setImageResource(header.iconRes);
836 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700837 holder.title.setText(header.getTitle(getContext().getResources()));
838 CharSequence summary = header.getSummary(getContext().getResources());
839 if (!TextUtils.isEmpty(summary)) {
840 holder.summary.setVisibility(View.VISIBLE);
841 holder.summary.setText(summary);
842 } else {
843 holder.summary.setVisibility(View.GONE);
844 }
845 break;
846 }
847
848 return view;
849 }
850
851 public void resume() {
852 mWifiEnabler.resume();
853 mBluetoothEnabler.resume();
854 }
Brian Muramatsuc28af522012-06-28 14:25:14 -0700855
Gilles Debunnee78c1872011-06-20 15:00:07 -0700856 public void pause() {
857 mWifiEnabler.pause();
858 mBluetoothEnabler.pause();
859 }
860 }
861
862 @Override
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700863 public void onHeaderClick(Header header, int position) {
864 boolean revert = false;
865 if (header.id == R.id.account_add) {
866 revert = true;
867 }
868
869 super.onHeaderClick(header, position);
870
871 if (revert && mLastHeader != null) {
872 highlightHeader((int) mLastHeader.id);
873 } else {
874 mLastHeader = header;
875 }
876 }
877
878 @Override
Amith Yamasania4379d62011-07-22 10:34:58 -0700879 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
880 // Override the fragment title for Wallpaper settings
Amith Yamasanidfb65432011-11-29 16:38:14 -0800881 int titleRes = pref.getTitleRes();
Amith Yamasania4379d62011-07-22 10:34:58 -0700882 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
Amith Yamasanidfb65432011-11-29 16:38:14 -0800883 titleRes = R.string.wallpaper_settings_fragment_title;
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700884 } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
885 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
Amith Yamasanib0171712013-04-28 22:13:22 -0700886 if (UserManager.get(this).isLinkedUser()) {
887 titleRes = R.string.profile_info_settings_title;
888 } else {
889 titleRes = R.string.user_info_settings_title;
890 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700891 }
Jean Chalard7dabe452012-05-10 18:08:07 +0900892 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
893 null, 0);
Amith Yamasania4379d62011-07-22 10:34:58 -0700894 return true;
895 }
896
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400897 @Override
Amith Yamasani3d384f42012-05-11 15:22:04 -0700898 public boolean shouldUpRecreateTask(Intent targetIntent) {
899 return super.shouldUpRecreateTask(new Intent(this, Settings.class));
900 }
901
Amith Yamasania4379d62011-07-22 10:34:58 -0700902 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700903 public void setListAdapter(ListAdapter adapter) {
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700904 if (adapter == null) {
905 super.setListAdapter(null);
906 } else {
907 super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700908 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700909 }
910
Amith Yamasani56821db2012-06-05 13:20:45 -0700911 @Override
912 public void onAccountsUpdated(Account[] accounts) {
Jeff Sharkey9ff79c12012-10-03 16:48:17 -0700913 // TODO: watch for package upgrades to invalidate cache; see 7206643
914 mAuthenticatorHelper.updateAuthDescriptions(this);
Amith Yamasani56821db2012-06-05 13:20:45 -0700915 mAuthenticatorHelper.onAccountsUpdated(this, accounts);
916 invalidateHeaders();
917 }
918
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700919 /*
920 * Settings subclasses for launching independently.
921 */
Gilles Debunnee78c1872011-06-20 15:00:07 -0700922 public static class BluetoothSettingsActivity extends Settings { /* empty */ }
923 public static class WirelessSettingsActivity extends Settings { /* empty */ }
924 public static class TetherSettingsActivity extends Settings { /* empty */ }
925 public static class VpnSettingsActivity extends Settings { /* empty */ }
926 public static class DateTimeSettingsActivity extends Settings { /* empty */ }
927 public static class StorageSettingsActivity extends Settings { /* empty */ }
928 public static class WifiSettingsActivity extends Settings { /* empty */ }
repo syncb98463f2011-06-30 10:58:43 -0700929 public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700930 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
Jeff Browne46c5f32012-04-05 11:42:18 -0700931 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700932 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
satoke077d2b2011-07-25 09:38:11 +0900933 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700934 public static class LocalePickerActivity extends Settings { /* empty */ }
935 public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
936 public static class SoundSettingsActivity extends Settings { /* empty */ }
937 public static class DisplaySettingsActivity extends Settings { /* empty */ }
938 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
939 public static class ApplicationSettingsActivity extends Settings { /* empty */ }
940 public static class ManageApplicationsActivity extends Settings { /* empty */ }
Dianne Hackborna522a8e2013-01-15 19:02:05 -0800941 public static class AppOpsSummaryActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700942 public static class StorageUseActivity extends Settings { /* empty */ }
943 public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
944 public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
Alan Viverette9b625f02013-09-11 13:03:14 -0700945 public static class CaptioningSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700946 public static class SecuritySettingsActivity extends Settings { /* empty */ }
Gilles Debunnea6a8a142011-06-09 11:56:17 -0700947 public static class LocationSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700948 public static class PrivacySettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700949 public static class RunningServicesActivity extends Settings { /* empty */ }
950 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
951 public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
952 public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
953 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
954 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
955 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
956 public static class DataUsageSummaryActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700957 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700958 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
Jeff Hamilton3d670de2011-09-21 16:44:36 -0500959 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
Jeff Brown9e143f52012-09-19 20:46:07 -0700960 public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
Daniel Sandler7dee75c2012-11-27 22:41:30 -0500961 public static class DreamSettingsActivity extends Settings { /* empty */ }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500962 public static class NotificationStationActivity extends Settings { /* empty */ }
Amith Yamasani233592b2013-03-01 17:05:23 -0800963 public static class UserSettingsActivity extends Settings { /* empty */ }
Daniel Sandler79b9bfe2013-04-04 14:30:04 -0400964 public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
Amith Yamasania677ee22013-07-26 13:38:41 -0700965 public static class UsbSettingsActivity extends Settings { /* empty */ }
Geoffrey Borggaardfc6bc202013-08-09 11:44:42 -0400966 public static class TrustedCredentialsSettingsActivity extends Settings { /* empty */ }
Martijn Coenen53083ab2013-08-09 13:37:38 -0700967 public static class PaymentSettingsActivity extends Settings { /* empty */ }
Svetoslav Ganov74648ac2013-09-04 23:52:28 -0700968 public static class PrintSettingsActivity extends Settings { /* empty */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800969}