blob: 62d4aa899c6d068c07dd7e7f8d818367aa9dddac [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;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080057import com.android.settings.accounts.AccountSyncSettings;
58import com.android.settings.accounts.AuthenticatorHelper;
59import com.android.settings.accounts.ManageAccountsSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070060import com.android.settings.applications.AppOpsSummary;
61import com.android.settings.applications.ManageApplications;
Dianne Hackbornc6d658e2013-08-08 12:57:53 -070062import com.android.settings.applications.ProcessStatsUi;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080063import com.android.settings.bluetooth.BluetoothEnabler;
64import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070065import com.android.settings.deviceinfo.Memory;
66import com.android.settings.deviceinfo.UsbSettings;
67import com.android.settings.fuelgauge.PowerUsageSummary;
68import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
Amith Yamasani3a14ae22013-08-30 15:43:44 -070069import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070070import com.android.settings.inputmethod.SpellCheckersSettings;
71import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070072import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070073import com.android.settings.nfc.AndroidBeam;
Martijn Coenen53083ab2013-08-09 13:37:38 -070074import com.android.settings.nfc.PaymentSettings;
Svetoslav2d531652013-09-03 21:32:40 -070075import com.android.settings.print.PrintServiceSettingsFragment;
76import com.android.settings.print.PrintSettingsFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070077import com.android.settings.tts.TextToSpeechSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070078import com.android.settings.users.UserSettings;
79import com.android.settings.vpn2.VpnSettings;
Jeff Sharkey0c3634c2013-02-20 12:35:16 -080080import com.android.settings.wfd.WifiDisplaySettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070081import com.android.settings.wifi.AdvancedWifiSettings;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080082import com.android.settings.wifi.WifiEnabler;
83import com.android.settings.wifi.WifiSettings;
84import com.android.settings.wifi.p2p.WifiP2pSettings;
85
Gilles Debunnee78c1872011-06-20 15:00:07 -070086import java.util.ArrayList;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070087import java.util.Collections;
88import java.util.Comparator;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070089import java.util.HashMap;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070090import java.util.List;
Amith Yamasanid7993472010-08-18 13:59:28 -070091
92/**
93 * Top-level settings activity to handle single pane and double pane UI layout.
94 */
Amith Yamasani56821db2012-06-05 13:20:45 -070095public class Settings extends PreferenceActivity
96 implements ButtonBarHandler, OnAccountsUpdateListener {
Amith Yamasanid7993472010-08-18 13:59:28 -070097
Gilles Debunnee78c1872011-06-20 15:00:07 -070098 private static final String LOG_TAG = "Settings";
Amith Yamasaniea7b28c2012-06-20 13:51:40 -070099
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700100 private static final String META_DATA_KEY_HEADER_ID =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700101 "com.android.settings.TOP_LEVEL_HEADER_ID";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700102 private static final String META_DATA_KEY_FRAGMENT_CLASS =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700103 "com.android.settings.FRAGMENT_CLASS";
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800104 private static final String META_DATA_KEY_PARENT_TITLE =
105 "com.android.settings.PARENT_FRAGMENT_TITLE";
106 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
107 "com.android.settings.PARENT_FRAGMENT_CLASS";
108
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800109 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700110
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800111 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
112 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700113
114 private String mFragmentClass;
115 private int mTopLevelHeaderId;
Amith Yamasani3965ae62010-11-15 14:45:19 -0800116 private Header mFirstHeader;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800117 private Header mCurrentHeader;
118 private Header mParentHeader;
119 private boolean mInLocalHeaderSwitch;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700120
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700121 // Show only these settings for restricted users
122 private int[] SETTINGS_FOR_RESTRICTED = {
Amith Yamasani32630392012-08-10 19:31:39 -0700123 R.id.wireless_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700124 R.id.wifi_settings,
125 R.id.bluetooth_settings,
Jeff Sharkey38305fb2012-09-14 16:26:51 -0700126 R.id.data_usage_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700127 R.id.wireless_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700128 R.id.device_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700129 R.id.sound_settings,
130 R.id.display_settings,
Jeff Sharkey90c8b202012-08-30 15:20:10 -0700131 R.id.storage_settings,
Dianne Hackborn271c8b02012-08-20 17:24:39 -0700132 R.id.application_settings,
Dianne Hackborn52e56a22012-09-12 17:02:23 -0700133 R.id.battery_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700134 R.id.personal_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700135 R.id.location_settings,
Amith Yamasani3deeeb72012-04-05 14:44:48 -0700136 R.id.security_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700137 R.id.language_settings,
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700138 R.id.user_settings,
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700139 R.id.account_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700140 R.id.account_add,
141 R.id.system_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700142 R.id.date_time_settings,
Jeff Brown9e143f52012-09-19 20:46:07 -0700143 R.id.about_settings,
Svetoslav Ganovd4c7b492013-06-11 21:15:11 -0700144 R.id.accessibility_settings,
Martijn Coenen26515da2013-08-01 18:13:33 -0700145 R.id.print_settings,
146 R.id.nfc_payment_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 Yamasani56f51a82013-08-05 10:07:23 -0700289 @Override
290 public boolean onIsMultiPane() {
291 return false;
292 }
293
Amith Yamasania677ee22013-07-26 13:38:41 -0700294 private static final String[] ENTRY_FRAGMENTS = {
295 WirelessSettings.class.getName(),
296 WifiSettings.class.getName(),
297 AdvancedWifiSettings.class.getName(),
298 BluetoothSettings.class.getName(),
299 TetherSettings.class.getName(),
300 WifiP2pSettings.class.getName(),
301 VpnSettings.class.getName(),
302 DateTimeSettings.class.getName(),
303 LocalePicker.class.getName(),
304 InputMethodAndLanguageSettings.class.getName(),
305 SpellCheckersSettings.class.getName(),
306 UserDictionaryList.class.getName(),
307 UserDictionarySettings.class.getName(),
308 SoundSettings.class.getName(),
309 DisplaySettings.class.getName(),
310 DeviceInfoSettings.class.getName(),
311 ManageApplications.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700312 ProcessStatsUi.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700313 NotificationStation.class.getName(),
314 AppOpsSummary.class.getName(),
315 LocationSettings.class.getName(),
316 SecuritySettings.class.getName(),
317 PrivacySettings.class.getName(),
318 DeviceAdminSettings.class.getName(),
319 AccessibilitySettings.class.getName(),
320 TextToSpeechSettings.class.getName(),
321 Memory.class.getName(),
322 DevelopmentSettings.class.getName(),
323 UsbSettings.class.getName(),
324 AndroidBeam.class.getName(),
325 WifiDisplaySettings.class.getName(),
326 PowerUsageSummary.class.getName(),
327 AccountSyncSettings.class.getName(),
328 CryptKeeperSettings.class.getName(),
329 DataUsageSummary.class.getName(),
330 DreamSettings.class.getName(),
331 UserSettings.class.getName(),
332 NotificationAccessSettings.class.getName(),
Amith Yamasaniee226f92013-08-05 11:02:16 -0700333 ManageAccountsSettings.class.getName(),
Svetoslav2d531652013-09-03 21:32:40 -0700334 PrintSettingsFragment.class.getName(),
Martijn Coenen53083ab2013-08-09 13:37:38 -0700335 TrustedCredentialsSettings.class.getName(),
Amith Yamasani3a14ae22013-08-30 15:43:44 -0700336 PaymentSettings.class.getName(),
337 KeyboardLayoutPickerFragment.class.getName()
Amith Yamasania677ee22013-07-26 13:38:41 -0700338 };
339
340 @Override
341 protected boolean isValidFragment(String fragmentName) {
342 // Almost all fragments are wrapped in this,
343 // except for a few that have their own activities.
344 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
345 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
346 }
347 return false;
348 }
349
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800350 private void switchToHeaderLocal(Header header) {
351 mInLocalHeaderSwitch = true;
352 switchToHeader(header);
353 mInLocalHeaderSwitch = false;
354 }
355
356 @Override
357 public void switchToHeader(Header header) {
358 if (!mInLocalHeaderSwitch) {
359 mCurrentHeader = null;
360 mParentHeader = null;
361 }
362 super.switchToHeader(header);
363 }
364
365 /**
366 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800367 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800368 */
369 private void switchToParent(String className) {
370 final ComponentName cn = new ComponentName(this, className);
371 try {
372 final PackageManager pm = getPackageManager();
373 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
374
375 if (parentInfo != null && parentInfo.metaData != null) {
376 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
377 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
378 Header parentHeader = new Header();
379 parentHeader.fragment = fragmentClass;
380 parentHeader.title = fragmentTitle;
381 mCurrentHeader = parentHeader;
382
383 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700384 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800385
386 mParentHeader = new Header();
387 mParentHeader.fragment
388 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
389 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
390 }
391 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700392 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800393 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700394 }
395
Amith Yamasani3965ae62010-11-15 14:45:19 -0800396 @Override
397 public void onNewIntent(Intent intent) {
398 super.onNewIntent(intent);
399
400 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700401 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
402 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
403 switchToHeaderLocal(mFirstHeader);
404 }
405 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800406 }
407 }
408
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700409 private void highlightHeader(int id) {
410 if (id != 0) {
411 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700412 if (index != null) {
413 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700414 if (isMultiPane()) {
415 getListView().smoothScrollToPosition(index);
416 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700417 }
418 }
419 }
420
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700421 @Override
422 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700423 Intent superIntent = super.getIntent();
424 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700425 // This is called from super.onCreate, isMultiPane() is not yet reliable
426 // Do not use onIsHidingHeaders either, which relies itself on this method
427 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700428 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700429 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700430 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700431 if (args != null) {
432 args = new Bundle(args);
433 } else {
434 args = new Bundle();
435 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700436 args.putParcelable("intent", superIntent);
437 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700438 return modIntent;
439 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700440 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700441 }
442
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700443 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700444 * Checks if the component name in the intent is different from the Settings class and
445 * returns the class name to load as a fragment.
446 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700447 protected String getStartingFragmentClass(Intent intent) {
448 if (mFragmentClass != null) return mFragmentClass;
449
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700450 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700451 if (intentClass.equals(getClass().getName())) return null;
452
Dianne Hackbornee293792010-11-01 12:32:33 -0700453 if ("com.android.settings.ManageApplications".equals(intentClass)
454 || "com.android.settings.RunningServices".equals(intentClass)
455 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700456 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700457 intentClass = com.android.settings.applications.ManageApplications.class.getName();
458 }
459
Amith Yamasani379d9b02010-09-27 12:03:59 -0700460 return intentClass;
461 }
462
463 /**
464 * Override initial header when an activity-alias is causing Settings to be launched
465 * for a specific fragment encoded in the android:name parameter.
466 */
467 @Override
468 public Header onGetInitialHeader() {
469 String fragmentClass = getStartingFragmentClass(super.getIntent());
470 if (fragmentClass != null) {
471 Header header = new Header();
472 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800473 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700474 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800475 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700476 return header;
477 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700478
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700479 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700480 }
481
Dianne Hackbornb7258182011-03-15 16:23:55 -0700482 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700483 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
484 int titleRes, int shortTitleRes) {
485 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
486 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700487
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800488 // Some fragments want split ActionBar; these should stay in sync with
489 // uiOptions for fragments also defined as activities in manifest.
490 if (WifiSettings.class.getName().equals(fragmentName) ||
491 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800492 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800493 BluetoothSettings.class.getName().equals(fragmentName) ||
494 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700495 LocationSettings.class.getName().equals(fragmentName) ||
Svetoslav2d531652013-09-03 21:32:40 -0700496 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName) ||
497 PrintSettingsFragment.class.getName().equals(fragmentName) ||
498 PrintServiceSettingsFragment.class.getName().equals(fragmentName)) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800499 intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700500 }
501
Dianne Hackbornb7258182011-03-15 16:23:55 -0700502 intent.setClass(this, SubSettings.class);
503 return intent;
504 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700505
Amith Yamasani379d9b02010-09-27 12:03:59 -0700506 /**
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700507 * Populate the activity with the top-level headers.
508 */
Amith Yamasanid7993472010-08-18 13:59:28 -0700509 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700510 public void onBuildHeaders(List<Header> headers) {
511 loadHeadersFromResource(R.xml.settings_headers, headers);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700512 updateHeaderList(headers);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700513 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700514
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700515 private void updateHeaderList(List<Header> target) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700516 final boolean showDev = mDevelopmentPreferences.getBoolean(
517 DevelopmentSettings.PREF_SHOW,
518 android.os.Build.TYPE.equals("eng"));
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700519 int i = 0;
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400520
521 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700522 mHeaderIndexMap.clear();
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700523 while (i < target.size()) {
524 Header header = target.get(i);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700525 // Ids are integers, so downcasting
526 int id = (int) header.id;
Chris Wren2bc32ae2012-09-24 14:23:46 -0400527 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700528 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
Gilles Debunne2454f492011-06-21 16:16:06 -0700529 } else if (id == R.id.wifi_settings) {
530 // Remove WiFi Settings if WiFi service is not available.
531 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700532 target.remove(i);
Gilles Debunne2454f492011-06-21 16:16:06 -0700533 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700534 } else if (id == R.id.bluetooth_settings) {
535 // Remove Bluetooth Settings if Bluetooth service is not available.
Gilles Debunne2454f492011-06-21 16:16:06 -0700536 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700537 target.remove(i);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700538 }
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700539 } else if (id == R.id.data_usage_settings) {
540 // Remove data usage when kernel module not enabled
541 final INetworkManagementService netManager = INetworkManagementService.Stub
542 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
543 try {
544 if (!netManager.isBandwidthControlEnabled()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700545 target.remove(i);
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700546 }
547 } catch (RemoteException e) {
548 // ignored
549 }
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900550 } else if (id == R.id.battery_settings) {
551 // Remove battery settings when battery is not available. (e.g. TV)
552
553 if (!mBatteryPresent) {
554 target.remove(i);
555 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700556 } else if (id == R.id.account_settings) {
557 int headerIndex = i + 1;
558 i = insertAccountsHeaders(target, headerIndex);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700559 } else if (id == R.id.user_settings) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700560 if (!UserHandle.MU_ENABLED
Jeff Sharkey44202462012-09-19 13:13:45 -0700561 || !UserManager.supportsMultipleUsers()
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700562 || Utils.isMonkeyRunning()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700563 target.remove(i);
564 }
Martijn Coenen26515da2013-08-01 18:13:33 -0700565 } else if (id == R.id.nfc_payment_settings) {
566 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
567 target.remove(i);
568 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700569 } else if (id == R.id.development_settings) {
570 if (!showDev) {
571 target.remove(i);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700572 }
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400573 } else if (id == R.id.account_add) {
574 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
575 target.remove(i);
576 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700577 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700578
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900579 if (i < target.size() && target.get(i) == header
Amith Yamasanib99f8642012-10-10 21:41:12 -0700580 && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700581 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700582 target.remove(i);
Amith Yamasanid7993472010-08-18 13:59:28 -0700583 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700584
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700585 // Increment if the current one wasn't removed by the Utils code.
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900586 if (i < target.size() && target.get(i) == header) {
Amith Yamasani3965ae62010-11-15 14:45:19 -0800587 // Hold on to the first header, when we need to reset to the top-level
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700588 if (mFirstHeader == null &&
589 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
590 mFirstHeader = header;
591 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700592 mHeaderIndexMap.put(id, i);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700593 i++;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700594 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700595 }
596 }
597
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700598 private int insertAccountsHeaders(List<Header> target, int headerIndex) {
599 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
600 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
601 for (String accountType : accountTypes) {
602 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
Brian Muramatsuc28af522012-06-28 14:25:14 -0700603 if (label == null) {
604 continue;
605 }
606
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700607 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
608 boolean skipToAccount = accounts.length == 1
609 && !mAuthenticatorHelper.hasAccountPreferences(accountType);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700610 Header accHeader = new Header();
611 accHeader.title = label;
612 if (accHeader.extras == null) {
613 accHeader.extras = new Bundle();
614 }
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700615 if (skipToAccount) {
616 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
617 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
618 accHeader.fragment = AccountSyncSettings.class.getName();
619 accHeader.fragmentArguments = new Bundle();
620 // Need this for the icon
621 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
622 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
623 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
624 accounts[0]);
625 } else {
626 accHeader.breadCrumbTitle = label;
627 accHeader.breadCrumbShortTitle = label;
628 accHeader.fragment = ManageAccountsSettings.class.getName();
629 accHeader.fragmentArguments = new Bundle();
630 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
631 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
632 accountType);
633 if (!isMultiPane()) {
634 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
635 label.toString());
636 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700637 }
638 accountHeaders.add(accHeader);
639 }
640
641 // Sort by label
642 Collections.sort(accountHeaders, new Comparator<Header>() {
643 @Override
644 public int compare(Header h1, Header h2) {
645 return h1.title.toString().compareTo(h2.title.toString());
646 }
647 });
648
649 for (Header header : accountHeaders) {
650 target.add(headerIndex++, header);
651 }
Amith Yamasani86708a82012-06-06 20:23:08 -0700652 if (!mListeningToAccountUpdates) {
653 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
654 mListeningToAccountUpdates = true;
655 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700656 return headerIndex;
657 }
658
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700659 private void getMetaData() {
660 try {
661 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
662 PackageManager.GET_META_DATA);
663 if (ai == null || ai.metaData == null) return;
664 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
665 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700666
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800667 // Check if it has a parent specified and create a Header object
668 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
669 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
670 if (parentFragmentClass != null) {
671 mParentHeader = new Header();
672 mParentHeader.fragment = parentFragmentClass;
673 if (parentHeaderTitleRes != 0) {
674 mParentHeader.title = getResources().getString(parentHeaderTitleRes);
675 }
676 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700677 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700678 // No recovery
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700679 }
680 }
681
Amith Yamasani9e3a4702011-01-11 09:09:26 -0800682 @Override
683 public boolean hasNextButton() {
684 return super.hasNextButton();
685 }
686
687 @Override
688 public Button getNextButton() {
689 return super.getNextButton();
690 }
691
Gilles Debunnee78c1872011-06-20 15:00:07 -0700692 private static class HeaderAdapter extends ArrayAdapter<Header> {
693 static final int HEADER_TYPE_CATEGORY = 0;
694 static final int HEADER_TYPE_NORMAL = 1;
695 static final int HEADER_TYPE_SWITCH = 2;
696 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
697
698 private final WifiEnabler mWifiEnabler;
699 private final BluetoothEnabler mBluetoothEnabler;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700700 private AuthenticatorHelper mAuthHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700701
702 private static class HeaderViewHolder {
703 ImageView icon;
704 TextView title;
705 TextView summary;
706 Switch switch_;
707 }
708
709 private LayoutInflater mInflater;
710
711 static int getHeaderType(Header header) {
712 if (header.fragment == null && header.intent == null) {
713 return HEADER_TYPE_CATEGORY;
714 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
715 return HEADER_TYPE_SWITCH;
716 } else {
717 return HEADER_TYPE_NORMAL;
718 }
719 }
720
721 @Override
722 public int getItemViewType(int position) {
723 Header header = getItem(position);
724 return getHeaderType(header);
725 }
726
727 @Override
728 public boolean areAllItemsEnabled() {
729 return false; // because of categories
730 }
731
732 @Override
733 public boolean isEnabled(int position) {
734 return getItemViewType(position) != HEADER_TYPE_CATEGORY;
735 }
736
737 @Override
738 public int getViewTypeCount() {
739 return HEADER_TYPE_COUNT;
740 }
741
742 @Override
743 public boolean hasStableIds() {
744 return true;
745 }
746
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700747 public HeaderAdapter(Context context, List<Header> objects,
748 AuthenticatorHelper authenticatorHelper) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700749 super(context, 0, objects);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700750
751 mAuthHelper = authenticatorHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700752 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700753
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700754 // Temp Switches provided as placeholder until the adapter replaces these with actual
Gilles Debunnee78c1872011-06-20 15:00:07 -0700755 // Switches inflated from their layouts. Must be done before adapter is set in super
756 mWifiEnabler = new WifiEnabler(context, new Switch(context));
757 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
758 }
759
760 @Override
761 public View getView(int position, View convertView, ViewGroup parent) {
762 HeaderViewHolder holder;
763 Header header = getItem(position);
764 int headerType = getHeaderType(header);
765 View view = null;
766
767 if (convertView == null) {
768 holder = new HeaderViewHolder();
769 switch (headerType) {
770 case HEADER_TYPE_CATEGORY:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700771 view = new TextView(getContext(), null,
772 android.R.attr.listSeparatorTextViewStyle);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700773 holder.title = (TextView) view;
774 break;
775
776 case HEADER_TYPE_SWITCH:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700777 view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
778 false);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700779 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700780 holder.title = (TextView)
781 view.findViewById(com.android.internal.R.id.title);
782 holder.summary = (TextView)
783 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700784 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
785 break;
786
787 case HEADER_TYPE_NORMAL:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700788 view = mInflater.inflate(
Amith Yamasanic8a93172012-06-08 13:35:47 -0700789 R.layout.preference_header_item, parent,
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700790 false);
Amith Yamasanic8a93172012-06-08 13:35:47 -0700791 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700792 holder.title = (TextView)
793 view.findViewById(com.android.internal.R.id.title);
794 holder.summary = (TextView)
795 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700796 break;
797 }
798 view.setTag(holder);
799 } else {
800 view = convertView;
801 holder = (HeaderViewHolder) view.getTag();
802 }
803
804 // All view fields must be updated every time, because the view may be recycled
805 switch (headerType) {
806 case HEADER_TYPE_CATEGORY:
807 holder.title.setText(header.getTitle(getContext().getResources()));
808 break;
809
810 case HEADER_TYPE_SWITCH:
811 // Would need a different treatment if the main menu had more switches
812 if (header.id == R.id.wifi_settings) {
813 mWifiEnabler.setSwitch(holder.switch_);
814 } else {
815 mBluetoothEnabler.setSwitch(holder.switch_);
816 }
817 // No break, fall through on purpose to update common fields
818
819 //$FALL-THROUGH$
820 case HEADER_TYPE_NORMAL:
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700821 if (header.extras != null
822 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700823 String accType = header.extras.getString(
824 ManageAccountsSettings.KEY_ACCOUNT_TYPE);
825 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
826 lp.width = getContext().getResources().getDimensionPixelSize(
827 R.dimen.header_icon_width);
828 lp.height = lp.width;
829 holder.icon.setLayoutParams(lp);
830 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
831 holder.icon.setImageDrawable(icon);
832 } else {
833 holder.icon.setImageResource(header.iconRes);
834 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700835 holder.title.setText(header.getTitle(getContext().getResources()));
836 CharSequence summary = header.getSummary(getContext().getResources());
837 if (!TextUtils.isEmpty(summary)) {
838 holder.summary.setVisibility(View.VISIBLE);
839 holder.summary.setText(summary);
840 } else {
841 holder.summary.setVisibility(View.GONE);
842 }
843 break;
844 }
845
846 return view;
847 }
848
849 public void resume() {
850 mWifiEnabler.resume();
851 mBluetoothEnabler.resume();
852 }
Brian Muramatsuc28af522012-06-28 14:25:14 -0700853
Gilles Debunnee78c1872011-06-20 15:00:07 -0700854 public void pause() {
855 mWifiEnabler.pause();
856 mBluetoothEnabler.pause();
857 }
858 }
859
860 @Override
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700861 public void onHeaderClick(Header header, int position) {
862 boolean revert = false;
863 if (header.id == R.id.account_add) {
864 revert = true;
865 }
866
867 super.onHeaderClick(header, position);
868
869 if (revert && mLastHeader != null) {
870 highlightHeader((int) mLastHeader.id);
871 } else {
872 mLastHeader = header;
873 }
874 }
875
876 @Override
Amith Yamasania4379d62011-07-22 10:34:58 -0700877 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
878 // Override the fragment title for Wallpaper settings
Amith Yamasanidfb65432011-11-29 16:38:14 -0800879 int titleRes = pref.getTitleRes();
Amith Yamasania4379d62011-07-22 10:34:58 -0700880 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
Amith Yamasanidfb65432011-11-29 16:38:14 -0800881 titleRes = R.string.wallpaper_settings_fragment_title;
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700882 } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
883 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
Amith Yamasanib0171712013-04-28 22:13:22 -0700884 if (UserManager.get(this).isLinkedUser()) {
885 titleRes = R.string.profile_info_settings_title;
886 } else {
887 titleRes = R.string.user_info_settings_title;
888 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700889 }
Jean Chalard7dabe452012-05-10 18:08:07 +0900890 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
891 null, 0);
Amith Yamasania4379d62011-07-22 10:34:58 -0700892 return true;
893 }
894
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400895 @Override
Amith Yamasani3d384f42012-05-11 15:22:04 -0700896 public boolean shouldUpRecreateTask(Intent targetIntent) {
897 return super.shouldUpRecreateTask(new Intent(this, Settings.class));
898 }
899
Amith Yamasania4379d62011-07-22 10:34:58 -0700900 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700901 public void setListAdapter(ListAdapter adapter) {
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700902 if (adapter == null) {
903 super.setListAdapter(null);
904 } else {
905 super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700906 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700907 }
908
Amith Yamasani56821db2012-06-05 13:20:45 -0700909 @Override
910 public void onAccountsUpdated(Account[] accounts) {
Jeff Sharkey9ff79c12012-10-03 16:48:17 -0700911 // TODO: watch for package upgrades to invalidate cache; see 7206643
912 mAuthenticatorHelper.updateAuthDescriptions(this);
Amith Yamasani56821db2012-06-05 13:20:45 -0700913 mAuthenticatorHelper.onAccountsUpdated(this, accounts);
914 invalidateHeaders();
915 }
916
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700917 /*
918 * Settings subclasses for launching independently.
919 */
Gilles Debunnee78c1872011-06-20 15:00:07 -0700920 public static class BluetoothSettingsActivity extends Settings { /* empty */ }
921 public static class WirelessSettingsActivity extends Settings { /* empty */ }
922 public static class TetherSettingsActivity extends Settings { /* empty */ }
923 public static class VpnSettingsActivity extends Settings { /* empty */ }
924 public static class DateTimeSettingsActivity extends Settings { /* empty */ }
925 public static class StorageSettingsActivity extends Settings { /* empty */ }
926 public static class WifiSettingsActivity extends Settings { /* empty */ }
repo syncb98463f2011-06-30 10:58:43 -0700927 public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700928 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
Jeff Browne46c5f32012-04-05 11:42:18 -0700929 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700930 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
satoke077d2b2011-07-25 09:38:11 +0900931 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700932 public static class LocalePickerActivity extends Settings { /* empty */ }
933 public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
934 public static class SoundSettingsActivity extends Settings { /* empty */ }
935 public static class DisplaySettingsActivity extends Settings { /* empty */ }
936 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
937 public static class ApplicationSettingsActivity extends Settings { /* empty */ }
938 public static class ManageApplicationsActivity extends Settings { /* empty */ }
Dianne Hackborna522a8e2013-01-15 19:02:05 -0800939 public static class AppOpsSummaryActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700940 public static class StorageUseActivity extends Settings { /* empty */ }
941 public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
942 public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
943 public static class SecuritySettingsActivity extends Settings { /* empty */ }
Gilles Debunnea6a8a142011-06-09 11:56:17 -0700944 public static class LocationSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700945 public static class PrivacySettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700946 public static class RunningServicesActivity extends Settings { /* empty */ }
947 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
948 public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
949 public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
950 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
951 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
952 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
953 public static class DataUsageSummaryActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700954 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700955 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
Jeff Hamilton3d670de2011-09-21 16:44:36 -0500956 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
Jeff Brown9e143f52012-09-19 20:46:07 -0700957 public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
Daniel Sandler7dee75c2012-11-27 22:41:30 -0500958 public static class DreamSettingsActivity extends Settings { /* empty */ }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500959 public static class NotificationStationActivity extends Settings { /* empty */ }
Amith Yamasani233592b2013-03-01 17:05:23 -0800960 public static class UserSettingsActivity extends Settings { /* empty */ }
Daniel Sandler79b9bfe2013-04-04 14:30:04 -0400961 public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
Amith Yamasania677ee22013-07-26 13:38:41 -0700962 public static class UsbSettingsActivity extends Settings { /* empty */ }
Geoffrey Borggaardfc6bc202013-08-09 11:44:42 -0400963 public static class TrustedCredentialsSettingsActivity extends Settings { /* empty */ }
Martijn Coenen53083ab2013-08-09 13:37:38 -0700964 public static class PaymentSettingsActivity extends Settings { /* empty */ }
Svetoslav Ganov74648ac2013-09-04 23:52:28 -0700965 public static class PrintSettingsActivity extends Settings { /* empty */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800966}