blob: 4221059b6a7f05cdff812345e1f2fe191ca795a2 [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;
Amith Yamasania677ee22013-07-26 13:38:41 -070022import android.app.Fragment;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090023import android.content.BroadcastReceiver;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080024import android.content.ComponentName;
Gilles Debunnee78c1872011-06-20 15:00:07 -070025import android.content.Context;
Amith Yamasani379d9b02010-09-27 12:03:59 -070026import android.content.Intent;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090027import android.content.IntentFilter;
Amith Yamasani233592b2013-03-01 17:05:23 -080028import android.content.RestrictionEntry;
Dianne Hackborncaefa9b2012-10-10 15:05:42 -070029import android.content.SharedPreferences;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070030import android.content.pm.ActivityInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070033import android.graphics.drawable.Drawable;
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -070034import android.os.Bundle;
Jeff Sharkey34e964d2012-04-21 15:41:48 -070035import android.os.INetworkManagementService;
36import android.os.RemoteException;
37import android.os.ServiceManager;
Dianne Hackbornbb06a422012-08-16 11:01:57 -070038import android.os.UserHandle;
Jeff Sharkey44202462012-09-19 13:13:45 -070039import android.os.UserManager;
Amith Yamasania4379d62011-07-22 10:34:58 -070040import android.preference.Preference;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070041import android.preference.PreferenceActivity;
Amith Yamasania4379d62011-07-22 10:34:58 -070042import android.preference.PreferenceFragment;
Gilles Debunnee78c1872011-06-20 15:00:07 -070043import android.text.TextUtils;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080044import android.util.Log;
Gilles Debunnee78c1872011-06-20 15:00:07 -070045import android.view.LayoutInflater;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080046import android.view.View;
47import android.view.View.OnClickListener;
Gilles Debunnee78c1872011-06-20 15:00:07 -070048import android.view.ViewGroup;
49import android.widget.ArrayAdapter;
Amith Yamasani9e3a4702011-01-11 09:09:26 -080050import android.widget.Button;
Gilles Debunnee78c1872011-06-20 15:00:07 -070051import android.widget.ImageView;
52import android.widget.ListAdapter;
53import android.widget.Switch;
54import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080055
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080056import com.android.internal.util.ArrayUtils;
Amith Yamasania677ee22013-07-26 13:38:41 -070057import com.android.settings.accessibility.AccessibilitySettings;
Alan Viverette341ff662013-07-18 17:49:33 -070058import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070059import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
60import com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment;
61import com.android.settings.ChooseLockPattern.ChooseLockPatternFragment;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080062import com.android.settings.accounts.AccountSyncSettings;
63import com.android.settings.accounts.AuthenticatorHelper;
64import com.android.settings.accounts.ManageAccountsSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070065import com.android.settings.applications.AppOpsSummary;
66import com.android.settings.applications.ManageApplications;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080067import com.android.settings.bluetooth.BluetoothEnabler;
68import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070069import com.android.settings.deviceinfo.Memory;
70import com.android.settings.deviceinfo.UsbSettings;
71import com.android.settings.fuelgauge.PowerUsageSummary;
72import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
73import com.android.settings.inputmethod.SpellCheckersSettings;
74import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070075import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070076import com.android.settings.nfc.AndroidBeam;
77import com.android.settings.tts.TextToSpeechSettings;
78import com.android.settings.users.AppRestrictionsFragment;
79import 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,
146 R.id.print_settings
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700147 };
148
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700149 private SharedPreferences mDevelopmentPreferences;
150 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
151
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700152 // TODO: Update Call Settings based on airplane mode state.
Amith Yamasanib61cf512010-09-12 08:17:50 -0700153
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700154 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
155
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700156 private AuthenticatorHelper mAuthenticatorHelper;
157 private Header mLastHeader;
Amith Yamasani86708a82012-06-06 20:23:08 -0700158 private boolean mListeningToAccountUpdates;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700159
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900160 private boolean mBatteryPresent = true;
161 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
162
163 @Override
164 public void onReceive(Context context, Intent intent) {
165 String action = intent.getAction();
166 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
167 boolean batteryPresent = Utils.isBatteryPresent(intent);
168
169 if (mBatteryPresent != batteryPresent) {
170 mBatteryPresent = batteryPresent;
171 invalidateHeaders();
172 }
173 }
174 }
175 };
176
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700177 @Override
178 protected void onCreate(Bundle savedInstanceState) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800179 if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
180 getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
Jeff Sharkey54d0af52011-08-11 18:26:57 -0700181 }
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700182
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700183 mAuthenticatorHelper = new AuthenticatorHelper();
184 mAuthenticatorHelper.updateAuthDescriptions(this);
185 mAuthenticatorHelper.onAccountsUpdated(this, null);
186
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700187 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
188 Context.MODE_PRIVATE);
189
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700190 getMetaData();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800191 mInLocalHeaderSwitch = true;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700192 super.onCreate(savedInstanceState);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800193 mInLocalHeaderSwitch = false;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700194
Gilles Debunne3661b622011-06-27 11:19:16 -0700195 if (!onIsHidingHeaders() && onIsMultiPane()) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700196 highlightHeader(mTopLevelHeaderId);
Amith Yamasani72aa19d2010-12-09 06:07:12 -0800197 // Force the title so that it doesn't get overridden by a direct launch of
198 // a specific settings screen.
199 setTitle(R.string.settings_label);
200 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800201
202 // Retrieve any saved state
203 if (savedInstanceState != null) {
204 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
205 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
206 }
207
208 // If the current header was saved, switch to it
209 if (savedInstanceState != null && mCurrentHeader != null) {
210 //switchToHeaderLocal(mCurrentHeader);
211 showBreadCrumbs(mCurrentHeader.title, null);
212 }
213
214 if (mParentHeader != null) {
215 setParentTitle(mParentHeader.title, null, new OnClickListener() {
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400216 @Override
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800217 public void onClick(View v) {
218 switchToParent(mParentHeader.fragment);
219 }
220 });
221 }
Gilles Debunnedc7101f2011-06-27 12:00:49 -0700222
Amith Yamasani3d384f42012-05-11 15:22:04 -0700223 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
224 if (onIsMultiPane()) {
225 getActionBar().setDisplayHomeAsUpEnabled(false);
226 getActionBar().setHomeButtonEnabled(false);
227 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800228 }
229
230 @Override
231 protected void onSaveInstanceState(Bundle outState) {
232 super.onSaveInstanceState(outState);
233
234 // Save the current fragment, if it is the same as originally launched
235 if (mCurrentHeader != null) {
236 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
237 }
238 if (mParentHeader != null) {
239 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
240 }
241 }
242
Gilles Debunnee78c1872011-06-20 15:00:07 -0700243 @Override
244 public void onResume() {
245 super.onResume();
246
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700247 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
248 @Override
249 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
250 invalidateHeaders();
251 }
252 };
253 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
254 mDevelopmentPreferencesListener);
255
Gilles Debunnee78c1872011-06-20 15:00:07 -0700256 ListAdapter listAdapter = getListAdapter();
257 if (listAdapter instanceof HeaderAdapter) {
258 ((HeaderAdapter) listAdapter).resume();
259 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700260 invalidateHeaders();
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900261
262 registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700263 }
264
265 @Override
266 public void onPause() {
267 super.onPause();
268
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900269 unregisterReceiver(mBatteryInfoReceiver);
270
Gilles Debunnee78c1872011-06-20 15:00:07 -0700271 ListAdapter listAdapter = getListAdapter();
272 if (listAdapter instanceof HeaderAdapter) {
273 ((HeaderAdapter) listAdapter).pause();
Amith Yamasani86708a82012-06-06 20:23:08 -0700274 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700275
276 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
277 mDevelopmentPreferencesListener);
278 mDevelopmentPreferencesListener = null;
Amith Yamasani86708a82012-06-06 20:23:08 -0700279 }
280
281 @Override
282 public void onDestroy() {
283 super.onDestroy();
284 if (mListeningToAccountUpdates) {
Amith Yamasani56821db2012-06-05 13:20:45 -0700285 AccountManager.get(this).removeOnAccountsUpdatedListener(this);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700286 }
287 }
288
Amith Yamasania677ee22013-07-26 13:38:41 -0700289 private static final String[] ENTRY_FRAGMENTS = {
290 WirelessSettings.class.getName(),
291 WifiSettings.class.getName(),
292 AdvancedWifiSettings.class.getName(),
293 BluetoothSettings.class.getName(),
294 TetherSettings.class.getName(),
295 WifiP2pSettings.class.getName(),
296 VpnSettings.class.getName(),
297 DateTimeSettings.class.getName(),
298 LocalePicker.class.getName(),
299 InputMethodAndLanguageSettings.class.getName(),
300 SpellCheckersSettings.class.getName(),
301 UserDictionaryList.class.getName(),
302 UserDictionarySettings.class.getName(),
303 SoundSettings.class.getName(),
304 DisplaySettings.class.getName(),
305 DeviceInfoSettings.class.getName(),
306 ManageApplications.class.getName(),
307 NotificationStation.class.getName(),
308 AppOpsSummary.class.getName(),
309 LocationSettings.class.getName(),
310 SecuritySettings.class.getName(),
311 PrivacySettings.class.getName(),
312 DeviceAdminSettings.class.getName(),
313 AccessibilitySettings.class.getName(),
314 TextToSpeechSettings.class.getName(),
315 Memory.class.getName(),
316 DevelopmentSettings.class.getName(),
317 UsbSettings.class.getName(),
318 AndroidBeam.class.getName(),
319 WifiDisplaySettings.class.getName(),
320 PowerUsageSummary.class.getName(),
321 AccountSyncSettings.class.getName(),
322 CryptKeeperSettings.class.getName(),
323 DataUsageSummary.class.getName(),
324 DreamSettings.class.getName(),
325 UserSettings.class.getName(),
326 NotificationAccessSettings.class.getName(),
Amith Yamasaniee226f92013-08-05 11:02:16 -0700327 ManageAccountsSettings.class.getName(),
328 PrintingSettings.class.getName()
Amith Yamasania677ee22013-07-26 13:38:41 -0700329 };
330
331 @Override
332 protected boolean isValidFragment(String fragmentName) {
333 // Almost all fragments are wrapped in this,
334 // except for a few that have their own activities.
335 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
336 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
337 }
338 return false;
339 }
340
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800341 private void switchToHeaderLocal(Header header) {
342 mInLocalHeaderSwitch = true;
343 switchToHeader(header);
344 mInLocalHeaderSwitch = false;
345 }
346
347 @Override
348 public void switchToHeader(Header header) {
349 if (!mInLocalHeaderSwitch) {
350 mCurrentHeader = null;
351 mParentHeader = null;
352 }
353 super.switchToHeader(header);
354 }
355
356 /**
357 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800358 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800359 */
360 private void switchToParent(String className) {
361 final ComponentName cn = new ComponentName(this, className);
362 try {
363 final PackageManager pm = getPackageManager();
364 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
365
366 if (parentInfo != null && parentInfo.metaData != null) {
367 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
368 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
369 Header parentHeader = new Header();
370 parentHeader.fragment = fragmentClass;
371 parentHeader.title = fragmentTitle;
372 mCurrentHeader = parentHeader;
373
374 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700375 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800376
377 mParentHeader = new Header();
378 mParentHeader.fragment
379 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
380 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
381 }
382 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700383 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800384 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700385 }
386
Amith Yamasani3965ae62010-11-15 14:45:19 -0800387 @Override
388 public void onNewIntent(Intent intent) {
389 super.onNewIntent(intent);
390
391 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700392 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
393 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
394 switchToHeaderLocal(mFirstHeader);
395 }
396 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800397 }
398 }
399
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700400 private void highlightHeader(int id) {
401 if (id != 0) {
402 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700403 if (index != null) {
404 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700405 if (isMultiPane()) {
406 getListView().smoothScrollToPosition(index);
407 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700408 }
409 }
410 }
411
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700412 @Override
413 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700414 Intent superIntent = super.getIntent();
415 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700416 // This is called from super.onCreate, isMultiPane() is not yet reliable
417 // Do not use onIsHidingHeaders either, which relies itself on this method
418 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700419 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700420 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700421 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700422 if (args != null) {
423 args = new Bundle(args);
424 } else {
425 args = new Bundle();
426 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700427 args.putParcelable("intent", superIntent);
428 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700429 return modIntent;
430 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700431 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700432 }
433
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700434 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700435 * Checks if the component name in the intent is different from the Settings class and
436 * returns the class name to load as a fragment.
437 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700438 protected String getStartingFragmentClass(Intent intent) {
439 if (mFragmentClass != null) return mFragmentClass;
440
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700441 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700442 if (intentClass.equals(getClass().getName())) return null;
443
Dianne Hackbornee293792010-11-01 12:32:33 -0700444 if ("com.android.settings.ManageApplications".equals(intentClass)
445 || "com.android.settings.RunningServices".equals(intentClass)
446 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700447 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700448 intentClass = com.android.settings.applications.ManageApplications.class.getName();
449 }
450
Amith Yamasani379d9b02010-09-27 12:03:59 -0700451 return intentClass;
452 }
453
454 /**
455 * Override initial header when an activity-alias is causing Settings to be launched
456 * for a specific fragment encoded in the android:name parameter.
457 */
458 @Override
459 public Header onGetInitialHeader() {
460 String fragmentClass = getStartingFragmentClass(super.getIntent());
461 if (fragmentClass != null) {
462 Header header = new Header();
463 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800464 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700465 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800466 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700467 return header;
468 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700469
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700470 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700471 }
472
Dianne Hackbornb7258182011-03-15 16:23:55 -0700473 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700474 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
475 int titleRes, int shortTitleRes) {
476 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
477 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700478
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800479 // Some fragments want split ActionBar; these should stay in sync with
480 // uiOptions for fragments also defined as activities in manifest.
481 if (WifiSettings.class.getName().equals(fragmentName) ||
482 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800483 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800484 BluetoothSettings.class.getName().equals(fragmentName) ||
485 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700486 LocationSettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800487 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName)) {
488 intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700489 }
490
Dianne Hackbornb7258182011-03-15 16:23:55 -0700491 intent.setClass(this, SubSettings.class);
492 return intent;
493 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700494
Amith Yamasani379d9b02010-09-27 12:03:59 -0700495 /**
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700496 * Populate the activity with the top-level headers.
497 */
Amith Yamasanid7993472010-08-18 13:59:28 -0700498 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700499 public void onBuildHeaders(List<Header> headers) {
500 loadHeadersFromResource(R.xml.settings_headers, headers);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700501 updateHeaderList(headers);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700502 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700503
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700504 private void updateHeaderList(List<Header> target) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700505 final boolean showDev = mDevelopmentPreferences.getBoolean(
506 DevelopmentSettings.PREF_SHOW,
507 android.os.Build.TYPE.equals("eng"));
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700508 int i = 0;
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400509
510 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700511 mHeaderIndexMap.clear();
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700512 while (i < target.size()) {
513 Header header = target.get(i);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700514 // Ids are integers, so downcasting
515 int id = (int) header.id;
Chris Wren2bc32ae2012-09-24 14:23:46 -0400516 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700517 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
Gilles Debunne2454f492011-06-21 16:16:06 -0700518 } else if (id == R.id.wifi_settings) {
519 // Remove WiFi Settings if WiFi service is not available.
520 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700521 target.remove(i);
Gilles Debunne2454f492011-06-21 16:16:06 -0700522 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700523 } else if (id == R.id.bluetooth_settings) {
524 // Remove Bluetooth Settings if Bluetooth service is not available.
Gilles Debunne2454f492011-06-21 16:16:06 -0700525 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700526 target.remove(i);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700527 }
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700528 } else if (id == R.id.data_usage_settings) {
529 // Remove data usage when kernel module not enabled
530 final INetworkManagementService netManager = INetworkManagementService.Stub
531 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
532 try {
533 if (!netManager.isBandwidthControlEnabled()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700534 target.remove(i);
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700535 }
536 } catch (RemoteException e) {
537 // ignored
538 }
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900539 } else if (id == R.id.battery_settings) {
540 // Remove battery settings when battery is not available. (e.g. TV)
541
542 if (!mBatteryPresent) {
543 target.remove(i);
544 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700545 } else if (id == R.id.account_settings) {
546 int headerIndex = i + 1;
547 i = insertAccountsHeaders(target, headerIndex);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700548 } else if (id == R.id.user_settings) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700549 if (!UserHandle.MU_ENABLED
Jeff Sharkey44202462012-09-19 13:13:45 -0700550 || !UserManager.supportsMultipleUsers()
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700551 || Utils.isMonkeyRunning()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700552 target.remove(i);
553 }
554 } else if (id == R.id.development_settings) {
555 if (!showDev) {
556 target.remove(i);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700557 }
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400558 } else if (id == R.id.account_add) {
559 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
560 target.remove(i);
561 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700562 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700563
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900564 if (i < target.size() && target.get(i) == header
Amith Yamasanib99f8642012-10-10 21:41:12 -0700565 && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700566 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700567 target.remove(i);
Amith Yamasanid7993472010-08-18 13:59:28 -0700568 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700569
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700570 // Increment if the current one wasn't removed by the Utils code.
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900571 if (i < target.size() && target.get(i) == header) {
Amith Yamasani3965ae62010-11-15 14:45:19 -0800572 // Hold on to the first header, when we need to reset to the top-level
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700573 if (mFirstHeader == null &&
574 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
575 mFirstHeader = header;
576 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700577 mHeaderIndexMap.put(id, i);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700578 i++;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700579 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700580 }
581 }
582
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700583 private int insertAccountsHeaders(List<Header> target, int headerIndex) {
584 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
585 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
586 for (String accountType : accountTypes) {
587 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
Brian Muramatsuc28af522012-06-28 14:25:14 -0700588 if (label == null) {
589 continue;
590 }
591
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700592 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
593 boolean skipToAccount = accounts.length == 1
594 && !mAuthenticatorHelper.hasAccountPreferences(accountType);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700595 Header accHeader = new Header();
596 accHeader.title = label;
597 if (accHeader.extras == null) {
598 accHeader.extras = new Bundle();
599 }
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700600 if (skipToAccount) {
601 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
602 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
603 accHeader.fragment = AccountSyncSettings.class.getName();
604 accHeader.fragmentArguments = new Bundle();
605 // Need this for the icon
606 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
607 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
608 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
609 accounts[0]);
610 } else {
611 accHeader.breadCrumbTitle = label;
612 accHeader.breadCrumbShortTitle = label;
613 accHeader.fragment = ManageAccountsSettings.class.getName();
614 accHeader.fragmentArguments = new Bundle();
615 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
616 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
617 accountType);
618 if (!isMultiPane()) {
619 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
620 label.toString());
621 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700622 }
623 accountHeaders.add(accHeader);
624 }
625
626 // Sort by label
627 Collections.sort(accountHeaders, new Comparator<Header>() {
628 @Override
629 public int compare(Header h1, Header h2) {
630 return h1.title.toString().compareTo(h2.title.toString());
631 }
632 });
633
634 for (Header header : accountHeaders) {
635 target.add(headerIndex++, header);
636 }
Amith Yamasani86708a82012-06-06 20:23:08 -0700637 if (!mListeningToAccountUpdates) {
638 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
639 mListeningToAccountUpdates = true;
640 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700641 return headerIndex;
642 }
643
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700644 private void getMetaData() {
645 try {
646 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
647 PackageManager.GET_META_DATA);
648 if (ai == null || ai.metaData == null) return;
649 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
650 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700651
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800652 // Check if it has a parent specified and create a Header object
653 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
654 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
655 if (parentFragmentClass != null) {
656 mParentHeader = new Header();
657 mParentHeader.fragment = parentFragmentClass;
658 if (parentHeaderTitleRes != 0) {
659 mParentHeader.title = getResources().getString(parentHeaderTitleRes);
660 }
661 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700662 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700663 // No recovery
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700664 }
665 }
666
Amith Yamasani9e3a4702011-01-11 09:09:26 -0800667 @Override
668 public boolean hasNextButton() {
669 return super.hasNextButton();
670 }
671
672 @Override
673 public Button getNextButton() {
674 return super.getNextButton();
675 }
676
Gilles Debunnee78c1872011-06-20 15:00:07 -0700677 private static class HeaderAdapter extends ArrayAdapter<Header> {
678 static final int HEADER_TYPE_CATEGORY = 0;
679 static final int HEADER_TYPE_NORMAL = 1;
680 static final int HEADER_TYPE_SWITCH = 2;
681 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
682
683 private final WifiEnabler mWifiEnabler;
684 private final BluetoothEnabler mBluetoothEnabler;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700685 private AuthenticatorHelper mAuthHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700686
687 private static class HeaderViewHolder {
688 ImageView icon;
689 TextView title;
690 TextView summary;
691 Switch switch_;
692 }
693
694 private LayoutInflater mInflater;
695
696 static int getHeaderType(Header header) {
697 if (header.fragment == null && header.intent == null) {
698 return HEADER_TYPE_CATEGORY;
699 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
700 return HEADER_TYPE_SWITCH;
701 } else {
702 return HEADER_TYPE_NORMAL;
703 }
704 }
705
706 @Override
707 public int getItemViewType(int position) {
708 Header header = getItem(position);
709 return getHeaderType(header);
710 }
711
712 @Override
713 public boolean areAllItemsEnabled() {
714 return false; // because of categories
715 }
716
717 @Override
718 public boolean isEnabled(int position) {
719 return getItemViewType(position) != HEADER_TYPE_CATEGORY;
720 }
721
722 @Override
723 public int getViewTypeCount() {
724 return HEADER_TYPE_COUNT;
725 }
726
727 @Override
728 public boolean hasStableIds() {
729 return true;
730 }
731
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700732 public HeaderAdapter(Context context, List<Header> objects,
733 AuthenticatorHelper authenticatorHelper) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700734 super(context, 0, objects);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700735
736 mAuthHelper = authenticatorHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700737 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700738
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700739 // Temp Switches provided as placeholder until the adapter replaces these with actual
Gilles Debunnee78c1872011-06-20 15:00:07 -0700740 // Switches inflated from their layouts. Must be done before adapter is set in super
741 mWifiEnabler = new WifiEnabler(context, new Switch(context));
742 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
743 }
744
745 @Override
746 public View getView(int position, View convertView, ViewGroup parent) {
747 HeaderViewHolder holder;
748 Header header = getItem(position);
749 int headerType = getHeaderType(header);
750 View view = null;
751
752 if (convertView == null) {
753 holder = new HeaderViewHolder();
754 switch (headerType) {
755 case HEADER_TYPE_CATEGORY:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700756 view = new TextView(getContext(), null,
757 android.R.attr.listSeparatorTextViewStyle);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700758 holder.title = (TextView) view;
759 break;
760
761 case HEADER_TYPE_SWITCH:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700762 view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
763 false);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700764 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700765 holder.title = (TextView)
766 view.findViewById(com.android.internal.R.id.title);
767 holder.summary = (TextView)
768 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700769 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
770 break;
771
772 case HEADER_TYPE_NORMAL:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700773 view = mInflater.inflate(
Amith Yamasanic8a93172012-06-08 13:35:47 -0700774 R.layout.preference_header_item, parent,
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700775 false);
Amith Yamasanic8a93172012-06-08 13:35:47 -0700776 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700777 holder.title = (TextView)
778 view.findViewById(com.android.internal.R.id.title);
779 holder.summary = (TextView)
780 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700781 break;
782 }
783 view.setTag(holder);
784 } else {
785 view = convertView;
786 holder = (HeaderViewHolder) view.getTag();
787 }
788
789 // All view fields must be updated every time, because the view may be recycled
790 switch (headerType) {
791 case HEADER_TYPE_CATEGORY:
792 holder.title.setText(header.getTitle(getContext().getResources()));
793 break;
794
795 case HEADER_TYPE_SWITCH:
796 // Would need a different treatment if the main menu had more switches
797 if (header.id == R.id.wifi_settings) {
798 mWifiEnabler.setSwitch(holder.switch_);
799 } else {
800 mBluetoothEnabler.setSwitch(holder.switch_);
801 }
802 // No break, fall through on purpose to update common fields
803
804 //$FALL-THROUGH$
805 case HEADER_TYPE_NORMAL:
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700806 if (header.extras != null
807 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700808 String accType = header.extras.getString(
809 ManageAccountsSettings.KEY_ACCOUNT_TYPE);
810 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
811 lp.width = getContext().getResources().getDimensionPixelSize(
812 R.dimen.header_icon_width);
813 lp.height = lp.width;
814 holder.icon.setLayoutParams(lp);
815 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
816 holder.icon.setImageDrawable(icon);
817 } else {
818 holder.icon.setImageResource(header.iconRes);
819 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700820 holder.title.setText(header.getTitle(getContext().getResources()));
821 CharSequence summary = header.getSummary(getContext().getResources());
822 if (!TextUtils.isEmpty(summary)) {
823 holder.summary.setVisibility(View.VISIBLE);
824 holder.summary.setText(summary);
825 } else {
826 holder.summary.setVisibility(View.GONE);
827 }
828 break;
829 }
830
831 return view;
832 }
833
834 public void resume() {
835 mWifiEnabler.resume();
836 mBluetoothEnabler.resume();
837 }
Brian Muramatsuc28af522012-06-28 14:25:14 -0700838
Gilles Debunnee78c1872011-06-20 15:00:07 -0700839 public void pause() {
840 mWifiEnabler.pause();
841 mBluetoothEnabler.pause();
842 }
843 }
844
845 @Override
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700846 public void onHeaderClick(Header header, int position) {
847 boolean revert = false;
848 if (header.id == R.id.account_add) {
849 revert = true;
850 }
851
852 super.onHeaderClick(header, position);
853
854 if (revert && mLastHeader != null) {
855 highlightHeader((int) mLastHeader.id);
856 } else {
857 mLastHeader = header;
858 }
859 }
860
861 @Override
Amith Yamasania4379d62011-07-22 10:34:58 -0700862 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
863 // Override the fragment title for Wallpaper settings
Amith Yamasanidfb65432011-11-29 16:38:14 -0800864 int titleRes = pref.getTitleRes();
Amith Yamasania4379d62011-07-22 10:34:58 -0700865 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
Amith Yamasanidfb65432011-11-29 16:38:14 -0800866 titleRes = R.string.wallpaper_settings_fragment_title;
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700867 } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
868 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
Amith Yamasanib0171712013-04-28 22:13:22 -0700869 if (UserManager.get(this).isLinkedUser()) {
870 titleRes = R.string.profile_info_settings_title;
871 } else {
872 titleRes = R.string.user_info_settings_title;
873 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700874 }
Jean Chalard7dabe452012-05-10 18:08:07 +0900875 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
876 null, 0);
Amith Yamasania4379d62011-07-22 10:34:58 -0700877 return true;
878 }
879
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400880 @Override
Amith Yamasani3d384f42012-05-11 15:22:04 -0700881 public boolean shouldUpRecreateTask(Intent targetIntent) {
882 return super.shouldUpRecreateTask(new Intent(this, Settings.class));
883 }
884
Amith Yamasania4379d62011-07-22 10:34:58 -0700885 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700886 public void setListAdapter(ListAdapter adapter) {
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700887 if (adapter == null) {
888 super.setListAdapter(null);
889 } else {
890 super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700891 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700892 }
893
Amith Yamasani56821db2012-06-05 13:20:45 -0700894 @Override
895 public void onAccountsUpdated(Account[] accounts) {
Jeff Sharkey9ff79c12012-10-03 16:48:17 -0700896 // TODO: watch for package upgrades to invalidate cache; see 7206643
897 mAuthenticatorHelper.updateAuthDescriptions(this);
Amith Yamasani56821db2012-06-05 13:20:45 -0700898 mAuthenticatorHelper.onAccountsUpdated(this, accounts);
899 invalidateHeaders();
900 }
901
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700902 /*
903 * Settings subclasses for launching independently.
904 */
Gilles Debunnee78c1872011-06-20 15:00:07 -0700905 public static class BluetoothSettingsActivity extends Settings { /* empty */ }
906 public static class WirelessSettingsActivity extends Settings { /* empty */ }
907 public static class TetherSettingsActivity extends Settings { /* empty */ }
908 public static class VpnSettingsActivity extends Settings { /* empty */ }
909 public static class DateTimeSettingsActivity extends Settings { /* empty */ }
910 public static class StorageSettingsActivity extends Settings { /* empty */ }
911 public static class WifiSettingsActivity extends Settings { /* empty */ }
repo syncb98463f2011-06-30 10:58:43 -0700912 public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700913 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
Jeff Browne46c5f32012-04-05 11:42:18 -0700914 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700915 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
satoke077d2b2011-07-25 09:38:11 +0900916 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700917 public static class LocalePickerActivity extends Settings { /* empty */ }
918 public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
919 public static class SoundSettingsActivity extends Settings { /* empty */ }
920 public static class DisplaySettingsActivity extends Settings { /* empty */ }
921 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
922 public static class ApplicationSettingsActivity extends Settings { /* empty */ }
923 public static class ManageApplicationsActivity extends Settings { /* empty */ }
Dianne Hackborna522a8e2013-01-15 19:02:05 -0800924 public static class AppOpsSummaryActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700925 public static class StorageUseActivity extends Settings { /* empty */ }
926 public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
927 public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
928 public static class SecuritySettingsActivity extends Settings { /* empty */ }
Gilles Debunnea6a8a142011-06-09 11:56:17 -0700929 public static class LocationSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700930 public static class PrivacySettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700931 public static class RunningServicesActivity extends Settings { /* empty */ }
932 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
933 public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
934 public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
935 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
936 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
937 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
938 public static class DataUsageSummaryActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700939 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700940 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
Jeff Hamilton3d670de2011-09-21 16:44:36 -0500941 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
Jeff Brown9e143f52012-09-19 20:46:07 -0700942 public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
Daniel Sandler7dee75c2012-11-27 22:41:30 -0500943 public static class DreamSettingsActivity extends Settings { /* empty */ }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500944 public static class NotificationStationActivity extends Settings { /* empty */ }
Amith Yamasani233592b2013-03-01 17:05:23 -0800945 public static class UserSettingsActivity extends Settings { /* empty */ }
Daniel Sandler79b9bfe2013-04-04 14:30:04 -0400946 public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
Amith Yamasania677ee22013-07-26 13:38:41 -0700947 public static class UsbSettingsActivity extends Settings { /* empty */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800948}