blob: a58d2b7cadc1cdbe8131edee0ca937cc5eee7f1c [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;
Dianne Hackbornc6d658e2013-08-08 12:57:53 -070067import com.android.settings.applications.ProcessStatsUi;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080068import com.android.settings.bluetooth.BluetoothEnabler;
69import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070070import com.android.settings.deviceinfo.Memory;
71import com.android.settings.deviceinfo.UsbSettings;
72import com.android.settings.fuelgauge.PowerUsageSummary;
73import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
74import com.android.settings.inputmethod.SpellCheckersSettings;
75import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070076import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070077import com.android.settings.nfc.AndroidBeam;
Martijn Coenen53083ab2013-08-09 13:37:38 -070078import com.android.settings.nfc.PaymentSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070079import com.android.settings.tts.TextToSpeechSettings;
80import com.android.settings.users.AppRestrictionsFragment;
81import com.android.settings.users.UserSettings;
82import com.android.settings.vpn2.VpnSettings;
Jeff Sharkey0c3634c2013-02-20 12:35:16 -080083import com.android.settings.wfd.WifiDisplaySettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070084import com.android.settings.wifi.AdvancedWifiSettings;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080085import com.android.settings.wifi.WifiEnabler;
86import com.android.settings.wifi.WifiSettings;
87import com.android.settings.wifi.p2p.WifiP2pSettings;
88
Gilles Debunnee78c1872011-06-20 15:00:07 -070089import java.util.ArrayList;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070090import java.util.Collections;
91import java.util.Comparator;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070092import java.util.HashMap;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070093import java.util.List;
Amith Yamasanid7993472010-08-18 13:59:28 -070094
95/**
96 * Top-level settings activity to handle single pane and double pane UI layout.
97 */
Amith Yamasani56821db2012-06-05 13:20:45 -070098public class Settings extends PreferenceActivity
99 implements ButtonBarHandler, OnAccountsUpdateListener {
Amith Yamasanid7993472010-08-18 13:59:28 -0700100
Gilles Debunnee78c1872011-06-20 15:00:07 -0700101 private static final String LOG_TAG = "Settings";
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700102
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700103 private static final String META_DATA_KEY_HEADER_ID =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700104 "com.android.settings.TOP_LEVEL_HEADER_ID";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700105 private static final String META_DATA_KEY_FRAGMENT_CLASS =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700106 "com.android.settings.FRAGMENT_CLASS";
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800107 private static final String META_DATA_KEY_PARENT_TITLE =
108 "com.android.settings.PARENT_FRAGMENT_TITLE";
109 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
110 "com.android.settings.PARENT_FRAGMENT_CLASS";
111
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800112 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700113
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800114 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
115 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700116
117 private String mFragmentClass;
118 private int mTopLevelHeaderId;
Amith Yamasani3965ae62010-11-15 14:45:19 -0800119 private Header mFirstHeader;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800120 private Header mCurrentHeader;
121 private Header mParentHeader;
122 private boolean mInLocalHeaderSwitch;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700123
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700124 // Show only these settings for restricted users
125 private int[] SETTINGS_FOR_RESTRICTED = {
Amith Yamasani32630392012-08-10 19:31:39 -0700126 R.id.wireless_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700127 R.id.wifi_settings,
128 R.id.bluetooth_settings,
Jeff Sharkey38305fb2012-09-14 16:26:51 -0700129 R.id.data_usage_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700130 R.id.wireless_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700131 R.id.device_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700132 R.id.sound_settings,
133 R.id.display_settings,
Jeff Sharkey90c8b202012-08-30 15:20:10 -0700134 R.id.storage_settings,
Dianne Hackborn271c8b02012-08-20 17:24:39 -0700135 R.id.application_settings,
Dianne Hackborn52e56a22012-09-12 17:02:23 -0700136 R.id.battery_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700137 R.id.personal_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700138 R.id.location_settings,
Amith Yamasani3deeeb72012-04-05 14:44:48 -0700139 R.id.security_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700140 R.id.language_settings,
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700141 R.id.user_settings,
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700142 R.id.account_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700143 R.id.account_add,
144 R.id.system_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700145 R.id.date_time_settings,
Jeff Brown9e143f52012-09-19 20:46:07 -0700146 R.id.about_settings,
Svetoslav Ganovd4c7b492013-06-11 21:15:11 -0700147 R.id.accessibility_settings,
Martijn Coenen26515da2013-08-01 18:13:33 -0700148 R.id.print_settings,
149 R.id.nfc_payment_settings
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700150 };
151
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700152 private SharedPreferences mDevelopmentPreferences;
153 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
154
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700155 // TODO: Update Call Settings based on airplane mode state.
Amith Yamasanib61cf512010-09-12 08:17:50 -0700156
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700157 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
158
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700159 private AuthenticatorHelper mAuthenticatorHelper;
160 private Header mLastHeader;
Amith Yamasani86708a82012-06-06 20:23:08 -0700161 private boolean mListeningToAccountUpdates;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700162
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900163 private boolean mBatteryPresent = true;
164 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
165
166 @Override
167 public void onReceive(Context context, Intent intent) {
168 String action = intent.getAction();
169 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
170 boolean batteryPresent = Utils.isBatteryPresent(intent);
171
172 if (mBatteryPresent != batteryPresent) {
173 mBatteryPresent = batteryPresent;
174 invalidateHeaders();
175 }
176 }
177 }
178 };
179
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700180 @Override
181 protected void onCreate(Bundle savedInstanceState) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800182 if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
183 getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
Jeff Sharkey54d0af52011-08-11 18:26:57 -0700184 }
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700185
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700186 mAuthenticatorHelper = new AuthenticatorHelper();
187 mAuthenticatorHelper.updateAuthDescriptions(this);
188 mAuthenticatorHelper.onAccountsUpdated(this, null);
189
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700190 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
191 Context.MODE_PRIVATE);
192
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700193 getMetaData();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800194 mInLocalHeaderSwitch = true;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700195 super.onCreate(savedInstanceState);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800196 mInLocalHeaderSwitch = false;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700197
Gilles Debunne3661b622011-06-27 11:19:16 -0700198 if (!onIsHidingHeaders() && onIsMultiPane()) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700199 highlightHeader(mTopLevelHeaderId);
Amith Yamasani72aa19d2010-12-09 06:07:12 -0800200 // Force the title so that it doesn't get overridden by a direct launch of
201 // a specific settings screen.
202 setTitle(R.string.settings_label);
203 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800204
205 // Retrieve any saved state
206 if (savedInstanceState != null) {
207 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
208 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
209 }
210
211 // If the current header was saved, switch to it
212 if (savedInstanceState != null && mCurrentHeader != null) {
213 //switchToHeaderLocal(mCurrentHeader);
214 showBreadCrumbs(mCurrentHeader.title, null);
215 }
216
217 if (mParentHeader != null) {
218 setParentTitle(mParentHeader.title, null, new OnClickListener() {
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400219 @Override
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800220 public void onClick(View v) {
221 switchToParent(mParentHeader.fragment);
222 }
223 });
224 }
Gilles Debunnedc7101f2011-06-27 12:00:49 -0700225
Amith Yamasani3d384f42012-05-11 15:22:04 -0700226 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
227 if (onIsMultiPane()) {
228 getActionBar().setDisplayHomeAsUpEnabled(false);
229 getActionBar().setHomeButtonEnabled(false);
230 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800231 }
232
233 @Override
234 protected void onSaveInstanceState(Bundle outState) {
235 super.onSaveInstanceState(outState);
236
237 // Save the current fragment, if it is the same as originally launched
238 if (mCurrentHeader != null) {
239 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
240 }
241 if (mParentHeader != null) {
242 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
243 }
244 }
245
Gilles Debunnee78c1872011-06-20 15:00:07 -0700246 @Override
247 public void onResume() {
248 super.onResume();
249
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700250 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
251 @Override
252 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
253 invalidateHeaders();
254 }
255 };
256 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
257 mDevelopmentPreferencesListener);
258
Gilles Debunnee78c1872011-06-20 15:00:07 -0700259 ListAdapter listAdapter = getListAdapter();
260 if (listAdapter instanceof HeaderAdapter) {
261 ((HeaderAdapter) listAdapter).resume();
262 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700263 invalidateHeaders();
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900264
265 registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700266 }
267
268 @Override
269 public void onPause() {
270 super.onPause();
271
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900272 unregisterReceiver(mBatteryInfoReceiver);
273
Gilles Debunnee78c1872011-06-20 15:00:07 -0700274 ListAdapter listAdapter = getListAdapter();
275 if (listAdapter instanceof HeaderAdapter) {
276 ((HeaderAdapter) listAdapter).pause();
Amith Yamasani86708a82012-06-06 20:23:08 -0700277 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700278
279 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
280 mDevelopmentPreferencesListener);
281 mDevelopmentPreferencesListener = null;
Amith Yamasani86708a82012-06-06 20:23:08 -0700282 }
283
284 @Override
285 public void onDestroy() {
286 super.onDestroy();
287 if (mListeningToAccountUpdates) {
Amith Yamasani56821db2012-06-05 13:20:45 -0700288 AccountManager.get(this).removeOnAccountsUpdatedListener(this);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700289 }
290 }
291
Amith Yamasani56f51a82013-08-05 10:07:23 -0700292 @Override
293 public boolean onIsMultiPane() {
294 return false;
295 }
296
Amith Yamasania677ee22013-07-26 13:38:41 -0700297 private static final String[] ENTRY_FRAGMENTS = {
298 WirelessSettings.class.getName(),
299 WifiSettings.class.getName(),
300 AdvancedWifiSettings.class.getName(),
301 BluetoothSettings.class.getName(),
302 TetherSettings.class.getName(),
303 WifiP2pSettings.class.getName(),
304 VpnSettings.class.getName(),
305 DateTimeSettings.class.getName(),
306 LocalePicker.class.getName(),
307 InputMethodAndLanguageSettings.class.getName(),
308 SpellCheckersSettings.class.getName(),
309 UserDictionaryList.class.getName(),
310 UserDictionarySettings.class.getName(),
311 SoundSettings.class.getName(),
312 DisplaySettings.class.getName(),
313 DeviceInfoSettings.class.getName(),
314 ManageApplications.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700315 ProcessStatsUi.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700316 NotificationStation.class.getName(),
317 AppOpsSummary.class.getName(),
318 LocationSettings.class.getName(),
319 SecuritySettings.class.getName(),
320 PrivacySettings.class.getName(),
321 DeviceAdminSettings.class.getName(),
322 AccessibilitySettings.class.getName(),
323 TextToSpeechSettings.class.getName(),
324 Memory.class.getName(),
325 DevelopmentSettings.class.getName(),
326 UsbSettings.class.getName(),
327 AndroidBeam.class.getName(),
328 WifiDisplaySettings.class.getName(),
329 PowerUsageSummary.class.getName(),
330 AccountSyncSettings.class.getName(),
331 CryptKeeperSettings.class.getName(),
332 DataUsageSummary.class.getName(),
333 DreamSettings.class.getName(),
334 UserSettings.class.getName(),
335 NotificationAccessSettings.class.getName(),
Amith Yamasaniee226f92013-08-05 11:02:16 -0700336 ManageAccountsSettings.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700337 PrintingSettings.class.getName(),
Martijn Coenen53083ab2013-08-09 13:37:38 -0700338 TrustedCredentialsSettings.class.getName(),
339 PaymentSettings.class.getName()
Amith Yamasania677ee22013-07-26 13:38:41 -0700340 };
341
342 @Override
343 protected boolean isValidFragment(String fragmentName) {
344 // Almost all fragments are wrapped in this,
345 // except for a few that have their own activities.
346 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
347 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
348 }
349 return false;
350 }
351
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800352 private void switchToHeaderLocal(Header header) {
353 mInLocalHeaderSwitch = true;
354 switchToHeader(header);
355 mInLocalHeaderSwitch = false;
356 }
357
358 @Override
359 public void switchToHeader(Header header) {
360 if (!mInLocalHeaderSwitch) {
361 mCurrentHeader = null;
362 mParentHeader = null;
363 }
364 super.switchToHeader(header);
365 }
366
367 /**
368 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800369 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800370 */
371 private void switchToParent(String className) {
372 final ComponentName cn = new ComponentName(this, className);
373 try {
374 final PackageManager pm = getPackageManager();
375 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
376
377 if (parentInfo != null && parentInfo.metaData != null) {
378 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
379 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
380 Header parentHeader = new Header();
381 parentHeader.fragment = fragmentClass;
382 parentHeader.title = fragmentTitle;
383 mCurrentHeader = parentHeader;
384
385 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700386 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800387
388 mParentHeader = new Header();
389 mParentHeader.fragment
390 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
391 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
392 }
393 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700394 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800395 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700396 }
397
Amith Yamasani3965ae62010-11-15 14:45:19 -0800398 @Override
399 public void onNewIntent(Intent intent) {
400 super.onNewIntent(intent);
401
402 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700403 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
404 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
405 switchToHeaderLocal(mFirstHeader);
406 }
407 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800408 }
409 }
410
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700411 private void highlightHeader(int id) {
412 if (id != 0) {
413 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700414 if (index != null) {
415 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700416 if (isMultiPane()) {
417 getListView().smoothScrollToPosition(index);
418 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700419 }
420 }
421 }
422
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700423 @Override
424 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700425 Intent superIntent = super.getIntent();
426 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700427 // This is called from super.onCreate, isMultiPane() is not yet reliable
428 // Do not use onIsHidingHeaders either, which relies itself on this method
429 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700430 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700431 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700432 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700433 if (args != null) {
434 args = new Bundle(args);
435 } else {
436 args = new Bundle();
437 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700438 args.putParcelable("intent", superIntent);
439 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700440 return modIntent;
441 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700442 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700443 }
444
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700445 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700446 * Checks if the component name in the intent is different from the Settings class and
447 * returns the class name to load as a fragment.
448 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700449 protected String getStartingFragmentClass(Intent intent) {
450 if (mFragmentClass != null) return mFragmentClass;
451
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700452 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700453 if (intentClass.equals(getClass().getName())) return null;
454
Dianne Hackbornee293792010-11-01 12:32:33 -0700455 if ("com.android.settings.ManageApplications".equals(intentClass)
456 || "com.android.settings.RunningServices".equals(intentClass)
457 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700458 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700459 intentClass = com.android.settings.applications.ManageApplications.class.getName();
460 }
461
Amith Yamasani379d9b02010-09-27 12:03:59 -0700462 return intentClass;
463 }
464
465 /**
466 * Override initial header when an activity-alias is causing Settings to be launched
467 * for a specific fragment encoded in the android:name parameter.
468 */
469 @Override
470 public Header onGetInitialHeader() {
471 String fragmentClass = getStartingFragmentClass(super.getIntent());
472 if (fragmentClass != null) {
473 Header header = new Header();
474 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800475 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700476 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800477 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700478 return header;
479 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700480
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700481 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700482 }
483
Dianne Hackbornb7258182011-03-15 16:23:55 -0700484 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700485 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
486 int titleRes, int shortTitleRes) {
487 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
488 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700489
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800490 // Some fragments want split ActionBar; these should stay in sync with
491 // uiOptions for fragments also defined as activities in manifest.
492 if (WifiSettings.class.getName().equals(fragmentName) ||
493 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800494 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800495 BluetoothSettings.class.getName().equals(fragmentName) ||
496 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700497 LocationSettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800498 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName)) {
499 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 */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800965}