blob: f5dbd3bdbf55a7a4dcbf7cbaf39189f3f04fd5e3 [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
Amith Yamasani56821db2012-06-05 13:20:45 -070019import android.accounts.Account;
20import android.accounts.AccountManager;
21import android.accounts.OnAccountsUpdateListener;
Amith Yamasania677ee22013-07-26 13:38:41 -070022import android.app.Fragment;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090023import android.content.BroadcastReceiver;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080024import android.content.ComponentName;
Gilles Debunnee78c1872011-06-20 15:00:07 -070025import android.content.Context;
Amith Yamasani379d9b02010-09-27 12:03:59 -070026import android.content.Intent;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090027import android.content.IntentFilter;
Amith Yamasani233592b2013-03-01 17:05:23 -080028import android.content.RestrictionEntry;
Dianne Hackborncaefa9b2012-10-10 15:05:42 -070029import android.content.SharedPreferences;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070030import android.content.pm.ActivityInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070033import android.graphics.drawable.Drawable;
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -070034import android.os.Bundle;
Jeff Sharkey34e964d2012-04-21 15:41:48 -070035import android.os.INetworkManagementService;
36import android.os.RemoteException;
37import android.os.ServiceManager;
Dianne Hackbornbb06a422012-08-16 11:01:57 -070038import android.os.UserHandle;
Jeff Sharkey44202462012-09-19 13:13:45 -070039import android.os.UserManager;
Amith Yamasania4379d62011-07-22 10:34:58 -070040import android.preference.Preference;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070041import android.preference.PreferenceActivity;
Amith Yamasania4379d62011-07-22 10:34:58 -070042import android.preference.PreferenceFragment;
Gilles Debunnee78c1872011-06-20 15:00:07 -070043import android.text.TextUtils;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080044import android.util.Log;
Gilles Debunnee78c1872011-06-20 15:00:07 -070045import android.view.LayoutInflater;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080046import android.view.View;
47import android.view.View.OnClickListener;
Gilles Debunnee78c1872011-06-20 15:00:07 -070048import android.view.ViewGroup;
49import android.widget.ArrayAdapter;
Amith Yamasani9e3a4702011-01-11 09:09:26 -080050import android.widget.Button;
Gilles Debunnee78c1872011-06-20 15:00:07 -070051import android.widget.ImageView;
52import android.widget.ListAdapter;
53import android.widget.Switch;
54import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080055
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080056import com.android.internal.util.ArrayUtils;
Amith Yamasania677ee22013-07-26 13:38:41 -070057import com.android.settings.accessibility.AccessibilitySettings;
Alan Viverette341ff662013-07-18 17:49:33 -070058import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070059import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
60import com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment;
61import com.android.settings.ChooseLockPattern.ChooseLockPatternFragment;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080062import com.android.settings.accounts.AccountSyncSettings;
63import com.android.settings.accounts.AuthenticatorHelper;
64import com.android.settings.accounts.ManageAccountsSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070065import com.android.settings.applications.AppOpsSummary;
66import com.android.settings.applications.ManageApplications;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080067import com.android.settings.bluetooth.BluetoothEnabler;
68import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070069import com.android.settings.deviceinfo.Memory;
70import com.android.settings.deviceinfo.UsbSettings;
71import com.android.settings.fuelgauge.PowerUsageSummary;
72import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
73import com.android.settings.inputmethod.SpellCheckersSettings;
74import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070075import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070076import com.android.settings.nfc.AndroidBeam;
77import com.android.settings.tts.TextToSpeechSettings;
78import com.android.settings.users.AppRestrictionsFragment;
79import com.android.settings.users.UserSettings;
80import com.android.settings.vpn2.VpnSettings;
Jeff Sharkey0c3634c2013-02-20 12:35:16 -080081import com.android.settings.wfd.WifiDisplaySettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070082import com.android.settings.wifi.AdvancedWifiSettings;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080083import com.android.settings.wifi.WifiEnabler;
84import com.android.settings.wifi.WifiSettings;
85import com.android.settings.wifi.p2p.WifiP2pSettings;
86
Gilles Debunnee78c1872011-06-20 15:00:07 -070087import java.util.ArrayList;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070088import java.util.Collections;
89import java.util.Comparator;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070090import java.util.HashMap;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070091import java.util.List;
Amith Yamasanid7993472010-08-18 13:59:28 -070092
93/**
94 * Top-level settings activity to handle single pane and double pane UI layout.
95 */
Amith Yamasani56821db2012-06-05 13:20:45 -070096public class Settings extends PreferenceActivity
97 implements ButtonBarHandler, OnAccountsUpdateListener {
Amith Yamasanid7993472010-08-18 13:59:28 -070098
Gilles Debunnee78c1872011-06-20 15:00:07 -070099 private static final String LOG_TAG = "Settings";
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700100
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700101 private static final String META_DATA_KEY_HEADER_ID =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700102 "com.android.settings.TOP_LEVEL_HEADER_ID";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700103 private static final String META_DATA_KEY_FRAGMENT_CLASS =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700104 "com.android.settings.FRAGMENT_CLASS";
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800105 private static final String META_DATA_KEY_PARENT_TITLE =
106 "com.android.settings.PARENT_FRAGMENT_TITLE";
107 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
108 "com.android.settings.PARENT_FRAGMENT_CLASS";
109
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800110 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700111
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800112 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
113 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700114
115 private String mFragmentClass;
116 private int mTopLevelHeaderId;
Amith Yamasani3965ae62010-11-15 14:45:19 -0800117 private Header mFirstHeader;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800118 private Header mCurrentHeader;
119 private Header mParentHeader;
120 private boolean mInLocalHeaderSwitch;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700121
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700122 // Show only these settings for restricted users
123 private int[] SETTINGS_FOR_RESTRICTED = {
Amith Yamasani32630392012-08-10 19:31:39 -0700124 R.id.wireless_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700125 R.id.wifi_settings,
126 R.id.bluetooth_settings,
Jeff Sharkey38305fb2012-09-14 16:26:51 -0700127 R.id.data_usage_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700128 R.id.wireless_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700129 R.id.device_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700130 R.id.sound_settings,
131 R.id.display_settings,
Jeff Sharkey90c8b202012-08-30 15:20:10 -0700132 R.id.storage_settings,
Dianne Hackborn271c8b02012-08-20 17:24:39 -0700133 R.id.application_settings,
Dianne Hackborn52e56a22012-09-12 17:02:23 -0700134 R.id.battery_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700135 R.id.personal_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700136 R.id.location_settings,
Amith Yamasani3deeeb72012-04-05 14:44:48 -0700137 R.id.security_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700138 R.id.language_settings,
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700139 R.id.user_settings,
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700140 R.id.account_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700141 R.id.account_add,
142 R.id.system_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700143 R.id.date_time_settings,
Jeff Brown9e143f52012-09-19 20:46:07 -0700144 R.id.about_settings,
Svetoslav Ganovd4c7b492013-06-11 21:15:11 -0700145 R.id.accessibility_settings,
Martijn Coenen26515da2013-08-01 18:13:33 -0700146 R.id.print_settings,
147 R.id.nfc_payment_settings
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700148 };
149
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700150 private SharedPreferences mDevelopmentPreferences;
151 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
152
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700153 // TODO: Update Call Settings based on airplane mode state.
Amith Yamasanib61cf512010-09-12 08:17:50 -0700154
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700155 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
156
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700157 private AuthenticatorHelper mAuthenticatorHelper;
158 private Header mLastHeader;
Amith Yamasani86708a82012-06-06 20:23:08 -0700159 private boolean mListeningToAccountUpdates;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700160
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900161 private boolean mBatteryPresent = true;
162 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
163
164 @Override
165 public void onReceive(Context context, Intent intent) {
166 String action = intent.getAction();
167 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
168 boolean batteryPresent = Utils.isBatteryPresent(intent);
169
170 if (mBatteryPresent != batteryPresent) {
171 mBatteryPresent = batteryPresent;
172 invalidateHeaders();
173 }
174 }
175 }
176 };
177
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700178 @Override
179 protected void onCreate(Bundle savedInstanceState) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800180 if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
181 getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
Jeff Sharkey54d0af52011-08-11 18:26:57 -0700182 }
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700183
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700184 mAuthenticatorHelper = new AuthenticatorHelper();
185 mAuthenticatorHelper.updateAuthDescriptions(this);
186 mAuthenticatorHelper.onAccountsUpdated(this, null);
187
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700188 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
189 Context.MODE_PRIVATE);
190
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700191 getMetaData();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800192 mInLocalHeaderSwitch = true;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700193 super.onCreate(savedInstanceState);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800194 mInLocalHeaderSwitch = false;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700195
Gilles Debunne3661b622011-06-27 11:19:16 -0700196 if (!onIsHidingHeaders() && onIsMultiPane()) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700197 highlightHeader(mTopLevelHeaderId);
Amith Yamasani72aa19d2010-12-09 06:07:12 -0800198 // Force the title so that it doesn't get overridden by a direct launch of
199 // a specific settings screen.
200 setTitle(R.string.settings_label);
201 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800202
203 // Retrieve any saved state
204 if (savedInstanceState != null) {
205 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
206 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
207 }
208
209 // If the current header was saved, switch to it
210 if (savedInstanceState != null && mCurrentHeader != null) {
211 //switchToHeaderLocal(mCurrentHeader);
212 showBreadCrumbs(mCurrentHeader.title, null);
213 }
214
215 if (mParentHeader != null) {
216 setParentTitle(mParentHeader.title, null, new OnClickListener() {
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400217 @Override
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800218 public void onClick(View v) {
219 switchToParent(mParentHeader.fragment);
220 }
221 });
222 }
Gilles Debunnedc7101f2011-06-27 12:00:49 -0700223
Amith Yamasani3d384f42012-05-11 15:22:04 -0700224 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
225 if (onIsMultiPane()) {
226 getActionBar().setDisplayHomeAsUpEnabled(false);
227 getActionBar().setHomeButtonEnabled(false);
228 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800229 }
230
231 @Override
232 protected void onSaveInstanceState(Bundle outState) {
233 super.onSaveInstanceState(outState);
234
235 // Save the current fragment, if it is the same as originally launched
236 if (mCurrentHeader != null) {
237 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
238 }
239 if (mParentHeader != null) {
240 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
241 }
242 }
243
Gilles Debunnee78c1872011-06-20 15:00:07 -0700244 @Override
245 public void onResume() {
246 super.onResume();
247
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700248 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
249 @Override
250 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
251 invalidateHeaders();
252 }
253 };
254 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
255 mDevelopmentPreferencesListener);
256
Gilles Debunnee78c1872011-06-20 15:00:07 -0700257 ListAdapter listAdapter = getListAdapter();
258 if (listAdapter instanceof HeaderAdapter) {
259 ((HeaderAdapter) listAdapter).resume();
260 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700261 invalidateHeaders();
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900262
263 registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700264 }
265
266 @Override
267 public void onPause() {
268 super.onPause();
269
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900270 unregisterReceiver(mBatteryInfoReceiver);
271
Gilles Debunnee78c1872011-06-20 15:00:07 -0700272 ListAdapter listAdapter = getListAdapter();
273 if (listAdapter instanceof HeaderAdapter) {
274 ((HeaderAdapter) listAdapter).pause();
Amith Yamasani86708a82012-06-06 20:23:08 -0700275 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700276
277 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
278 mDevelopmentPreferencesListener);
279 mDevelopmentPreferencesListener = null;
Amith Yamasani86708a82012-06-06 20:23:08 -0700280 }
281
282 @Override
283 public void onDestroy() {
284 super.onDestroy();
285 if (mListeningToAccountUpdates) {
Amith Yamasani56821db2012-06-05 13:20:45 -0700286 AccountManager.get(this).removeOnAccountsUpdatedListener(this);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700287 }
288 }
289
Amith Yamasani56f51a82013-08-05 10:07:23 -0700290 @Override
291 public boolean onIsMultiPane() {
292 return false;
293 }
294
Amith Yamasania677ee22013-07-26 13:38:41 -0700295 private static final String[] ENTRY_FRAGMENTS = {
296 WirelessSettings.class.getName(),
297 WifiSettings.class.getName(),
298 AdvancedWifiSettings.class.getName(),
299 BluetoothSettings.class.getName(),
300 TetherSettings.class.getName(),
301 WifiP2pSettings.class.getName(),
302 VpnSettings.class.getName(),
303 DateTimeSettings.class.getName(),
304 LocalePicker.class.getName(),
305 InputMethodAndLanguageSettings.class.getName(),
306 SpellCheckersSettings.class.getName(),
307 UserDictionaryList.class.getName(),
308 UserDictionarySettings.class.getName(),
309 SoundSettings.class.getName(),
310 DisplaySettings.class.getName(),
311 DeviceInfoSettings.class.getName(),
312 ManageApplications.class.getName(),
313 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(),
334 PrintingSettings.class.getName()
Amith Yamasania677ee22013-07-26 13:38:41 -0700335 };
336
337 @Override
338 protected boolean isValidFragment(String fragmentName) {
339 // Almost all fragments are wrapped in this,
340 // except for a few that have their own activities.
341 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
342 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
343 }
344 return false;
345 }
346
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800347 private void switchToHeaderLocal(Header header) {
348 mInLocalHeaderSwitch = true;
349 switchToHeader(header);
350 mInLocalHeaderSwitch = false;
351 }
352
353 @Override
354 public void switchToHeader(Header header) {
355 if (!mInLocalHeaderSwitch) {
356 mCurrentHeader = null;
357 mParentHeader = null;
358 }
359 super.switchToHeader(header);
360 }
361
362 /**
363 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800364 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800365 */
366 private void switchToParent(String className) {
367 final ComponentName cn = new ComponentName(this, className);
368 try {
369 final PackageManager pm = getPackageManager();
370 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
371
372 if (parentInfo != null && parentInfo.metaData != null) {
373 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
374 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
375 Header parentHeader = new Header();
376 parentHeader.fragment = fragmentClass;
377 parentHeader.title = fragmentTitle;
378 mCurrentHeader = parentHeader;
379
380 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700381 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800382
383 mParentHeader = new Header();
384 mParentHeader.fragment
385 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
386 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
387 }
388 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700389 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800390 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700391 }
392
Amith Yamasani3965ae62010-11-15 14:45:19 -0800393 @Override
394 public void onNewIntent(Intent intent) {
395 super.onNewIntent(intent);
396
397 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700398 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
399 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
400 switchToHeaderLocal(mFirstHeader);
401 }
402 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800403 }
404 }
405
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700406 private void highlightHeader(int id) {
407 if (id != 0) {
408 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700409 if (index != null) {
410 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700411 if (isMultiPane()) {
412 getListView().smoothScrollToPosition(index);
413 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700414 }
415 }
416 }
417
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700418 @Override
419 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700420 Intent superIntent = super.getIntent();
421 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700422 // This is called from super.onCreate, isMultiPane() is not yet reliable
423 // Do not use onIsHidingHeaders either, which relies itself on this method
424 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700425 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700426 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700427 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700428 if (args != null) {
429 args = new Bundle(args);
430 } else {
431 args = new Bundle();
432 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700433 args.putParcelable("intent", superIntent);
434 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700435 return modIntent;
436 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700437 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700438 }
439
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700440 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700441 * Checks if the component name in the intent is different from the Settings class and
442 * returns the class name to load as a fragment.
443 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700444 protected String getStartingFragmentClass(Intent intent) {
445 if (mFragmentClass != null) return mFragmentClass;
446
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700447 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700448 if (intentClass.equals(getClass().getName())) return null;
449
Dianne Hackbornee293792010-11-01 12:32:33 -0700450 if ("com.android.settings.ManageApplications".equals(intentClass)
451 || "com.android.settings.RunningServices".equals(intentClass)
452 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700453 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700454 intentClass = com.android.settings.applications.ManageApplications.class.getName();
455 }
456
Amith Yamasani379d9b02010-09-27 12:03:59 -0700457 return intentClass;
458 }
459
460 /**
461 * Override initial header when an activity-alias is causing Settings to be launched
462 * for a specific fragment encoded in the android:name parameter.
463 */
464 @Override
465 public Header onGetInitialHeader() {
466 String fragmentClass = getStartingFragmentClass(super.getIntent());
467 if (fragmentClass != null) {
468 Header header = new Header();
469 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800470 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700471 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800472 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700473 return header;
474 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700475
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700476 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700477 }
478
Dianne Hackbornb7258182011-03-15 16:23:55 -0700479 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700480 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
481 int titleRes, int shortTitleRes) {
482 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
483 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700484
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800485 // Some fragments want split ActionBar; these should stay in sync with
486 // uiOptions for fragments also defined as activities in manifest.
487 if (WifiSettings.class.getName().equals(fragmentName) ||
488 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800489 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800490 BluetoothSettings.class.getName().equals(fragmentName) ||
491 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700492 LocationSettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800493 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName)) {
494 intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700495 }
496
Dianne Hackbornb7258182011-03-15 16:23:55 -0700497 intent.setClass(this, SubSettings.class);
498 return intent;
499 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700500
Amith Yamasani379d9b02010-09-27 12:03:59 -0700501 /**
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700502 * Populate the activity with the top-level headers.
503 */
Amith Yamasanid7993472010-08-18 13:59:28 -0700504 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700505 public void onBuildHeaders(List<Header> headers) {
506 loadHeadersFromResource(R.xml.settings_headers, headers);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700507 updateHeaderList(headers);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700508 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700509
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700510 private void updateHeaderList(List<Header> target) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700511 final boolean showDev = mDevelopmentPreferences.getBoolean(
512 DevelopmentSettings.PREF_SHOW,
513 android.os.Build.TYPE.equals("eng"));
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700514 int i = 0;
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400515
516 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700517 mHeaderIndexMap.clear();
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700518 while (i < target.size()) {
519 Header header = target.get(i);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700520 // Ids are integers, so downcasting
521 int id = (int) header.id;
Chris Wren2bc32ae2012-09-24 14:23:46 -0400522 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700523 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
Gilles Debunne2454f492011-06-21 16:16:06 -0700524 } else if (id == R.id.wifi_settings) {
525 // Remove WiFi Settings if WiFi service is not available.
526 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700527 target.remove(i);
Gilles Debunne2454f492011-06-21 16:16:06 -0700528 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700529 } else if (id == R.id.bluetooth_settings) {
530 // Remove Bluetooth Settings if Bluetooth service is not available.
Gilles Debunne2454f492011-06-21 16:16:06 -0700531 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700532 target.remove(i);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700533 }
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700534 } else if (id == R.id.data_usage_settings) {
535 // Remove data usage when kernel module not enabled
536 final INetworkManagementService netManager = INetworkManagementService.Stub
537 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
538 try {
539 if (!netManager.isBandwidthControlEnabled()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700540 target.remove(i);
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700541 }
542 } catch (RemoteException e) {
543 // ignored
544 }
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900545 } else if (id == R.id.battery_settings) {
546 // Remove battery settings when battery is not available. (e.g. TV)
547
548 if (!mBatteryPresent) {
549 target.remove(i);
550 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700551 } else if (id == R.id.account_settings) {
552 int headerIndex = i + 1;
553 i = insertAccountsHeaders(target, headerIndex);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700554 } else if (id == R.id.user_settings) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700555 if (!UserHandle.MU_ENABLED
Jeff Sharkey44202462012-09-19 13:13:45 -0700556 || !UserManager.supportsMultipleUsers()
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700557 || Utils.isMonkeyRunning()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700558 target.remove(i);
559 }
Martijn Coenen26515da2013-08-01 18:13:33 -0700560 } else if (id == R.id.nfc_payment_settings) {
561 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
562 target.remove(i);
563 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700564 } else if (id == R.id.development_settings) {
565 if (!showDev) {
566 target.remove(i);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700567 }
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400568 } else if (id == R.id.account_add) {
569 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
570 target.remove(i);
571 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700572 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700573
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900574 if (i < target.size() && target.get(i) == header
Amith Yamasanib99f8642012-10-10 21:41:12 -0700575 && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700576 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700577 target.remove(i);
Amith Yamasanid7993472010-08-18 13:59:28 -0700578 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700579
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700580 // Increment if the current one wasn't removed by the Utils code.
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900581 if (i < target.size() && target.get(i) == header) {
Amith Yamasani3965ae62010-11-15 14:45:19 -0800582 // Hold on to the first header, when we need to reset to the top-level
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700583 if (mFirstHeader == null &&
584 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
585 mFirstHeader = header;
586 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700587 mHeaderIndexMap.put(id, i);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700588 i++;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700589 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700590 }
591 }
592
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700593 private int insertAccountsHeaders(List<Header> target, int headerIndex) {
594 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
595 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
596 for (String accountType : accountTypes) {
597 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
Brian Muramatsuc28af522012-06-28 14:25:14 -0700598 if (label == null) {
599 continue;
600 }
601
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700602 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
603 boolean skipToAccount = accounts.length == 1
604 && !mAuthenticatorHelper.hasAccountPreferences(accountType);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700605 Header accHeader = new Header();
606 accHeader.title = label;
607 if (accHeader.extras == null) {
608 accHeader.extras = new Bundle();
609 }
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700610 if (skipToAccount) {
611 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
612 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
613 accHeader.fragment = AccountSyncSettings.class.getName();
614 accHeader.fragmentArguments = new Bundle();
615 // Need this for the icon
616 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
617 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
618 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
619 accounts[0]);
620 } else {
621 accHeader.breadCrumbTitle = label;
622 accHeader.breadCrumbShortTitle = label;
623 accHeader.fragment = ManageAccountsSettings.class.getName();
624 accHeader.fragmentArguments = new Bundle();
625 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
626 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
627 accountType);
628 if (!isMultiPane()) {
629 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
630 label.toString());
631 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700632 }
633 accountHeaders.add(accHeader);
634 }
635
636 // Sort by label
637 Collections.sort(accountHeaders, new Comparator<Header>() {
638 @Override
639 public int compare(Header h1, Header h2) {
640 return h1.title.toString().compareTo(h2.title.toString());
641 }
642 });
643
644 for (Header header : accountHeaders) {
645 target.add(headerIndex++, header);
646 }
Amith Yamasani86708a82012-06-06 20:23:08 -0700647 if (!mListeningToAccountUpdates) {
648 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
649 mListeningToAccountUpdates = true;
650 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700651 return headerIndex;
652 }
653
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700654 private void getMetaData() {
655 try {
656 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
657 PackageManager.GET_META_DATA);
658 if (ai == null || ai.metaData == null) return;
659 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
660 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700661
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800662 // Check if it has a parent specified and create a Header object
663 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
664 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
665 if (parentFragmentClass != null) {
666 mParentHeader = new Header();
667 mParentHeader.fragment = parentFragmentClass;
668 if (parentHeaderTitleRes != 0) {
669 mParentHeader.title = getResources().getString(parentHeaderTitleRes);
670 }
671 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700672 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700673 // No recovery
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700674 }
675 }
676
Amith Yamasani9e3a4702011-01-11 09:09:26 -0800677 @Override
678 public boolean hasNextButton() {
679 return super.hasNextButton();
680 }
681
682 @Override
683 public Button getNextButton() {
684 return super.getNextButton();
685 }
686
Gilles Debunnee78c1872011-06-20 15:00:07 -0700687 private static class HeaderAdapter extends ArrayAdapter<Header> {
688 static final int HEADER_TYPE_CATEGORY = 0;
689 static final int HEADER_TYPE_NORMAL = 1;
690 static final int HEADER_TYPE_SWITCH = 2;
691 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
692
693 private final WifiEnabler mWifiEnabler;
694 private final BluetoothEnabler mBluetoothEnabler;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700695 private AuthenticatorHelper mAuthHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700696
697 private static class HeaderViewHolder {
698 ImageView icon;
699 TextView title;
700 TextView summary;
701 Switch switch_;
702 }
703
704 private LayoutInflater mInflater;
705
706 static int getHeaderType(Header header) {
707 if (header.fragment == null && header.intent == null) {
708 return HEADER_TYPE_CATEGORY;
709 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
710 return HEADER_TYPE_SWITCH;
711 } else {
712 return HEADER_TYPE_NORMAL;
713 }
714 }
715
716 @Override
717 public int getItemViewType(int position) {
718 Header header = getItem(position);
719 return getHeaderType(header);
720 }
721
722 @Override
723 public boolean areAllItemsEnabled() {
724 return false; // because of categories
725 }
726
727 @Override
728 public boolean isEnabled(int position) {
729 return getItemViewType(position) != HEADER_TYPE_CATEGORY;
730 }
731
732 @Override
733 public int getViewTypeCount() {
734 return HEADER_TYPE_COUNT;
735 }
736
737 @Override
738 public boolean hasStableIds() {
739 return true;
740 }
741
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700742 public HeaderAdapter(Context context, List<Header> objects,
743 AuthenticatorHelper authenticatorHelper) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700744 super(context, 0, objects);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700745
746 mAuthHelper = authenticatorHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700747 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700748
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700749 // Temp Switches provided as placeholder until the adapter replaces these with actual
Gilles Debunnee78c1872011-06-20 15:00:07 -0700750 // Switches inflated from their layouts. Must be done before adapter is set in super
751 mWifiEnabler = new WifiEnabler(context, new Switch(context));
752 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
753 }
754
755 @Override
756 public View getView(int position, View convertView, ViewGroup parent) {
757 HeaderViewHolder holder;
758 Header header = getItem(position);
759 int headerType = getHeaderType(header);
760 View view = null;
761
762 if (convertView == null) {
763 holder = new HeaderViewHolder();
764 switch (headerType) {
765 case HEADER_TYPE_CATEGORY:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700766 view = new TextView(getContext(), null,
767 android.R.attr.listSeparatorTextViewStyle);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700768 holder.title = (TextView) view;
769 break;
770
771 case HEADER_TYPE_SWITCH:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700772 view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
773 false);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700774 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700775 holder.title = (TextView)
776 view.findViewById(com.android.internal.R.id.title);
777 holder.summary = (TextView)
778 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700779 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
780 break;
781
782 case HEADER_TYPE_NORMAL:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700783 view = mInflater.inflate(
Amith Yamasanic8a93172012-06-08 13:35:47 -0700784 R.layout.preference_header_item, parent,
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700785 false);
Amith Yamasanic8a93172012-06-08 13:35:47 -0700786 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700787 holder.title = (TextView)
788 view.findViewById(com.android.internal.R.id.title);
789 holder.summary = (TextView)
790 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700791 break;
792 }
793 view.setTag(holder);
794 } else {
795 view = convertView;
796 holder = (HeaderViewHolder) view.getTag();
797 }
798
799 // All view fields must be updated every time, because the view may be recycled
800 switch (headerType) {
801 case HEADER_TYPE_CATEGORY:
802 holder.title.setText(header.getTitle(getContext().getResources()));
803 break;
804
805 case HEADER_TYPE_SWITCH:
806 // Would need a different treatment if the main menu had more switches
807 if (header.id == R.id.wifi_settings) {
808 mWifiEnabler.setSwitch(holder.switch_);
809 } else {
810 mBluetoothEnabler.setSwitch(holder.switch_);
811 }
812 // No break, fall through on purpose to update common fields
813
814 //$FALL-THROUGH$
815 case HEADER_TYPE_NORMAL:
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700816 if (header.extras != null
817 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700818 String accType = header.extras.getString(
819 ManageAccountsSettings.KEY_ACCOUNT_TYPE);
820 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
821 lp.width = getContext().getResources().getDimensionPixelSize(
822 R.dimen.header_icon_width);
823 lp.height = lp.width;
824 holder.icon.setLayoutParams(lp);
825 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
826 holder.icon.setImageDrawable(icon);
827 } else {
828 holder.icon.setImageResource(header.iconRes);
829 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700830 holder.title.setText(header.getTitle(getContext().getResources()));
831 CharSequence summary = header.getSummary(getContext().getResources());
832 if (!TextUtils.isEmpty(summary)) {
833 holder.summary.setVisibility(View.VISIBLE);
834 holder.summary.setText(summary);
835 } else {
836 holder.summary.setVisibility(View.GONE);
837 }
838 break;
839 }
840
841 return view;
842 }
843
844 public void resume() {
845 mWifiEnabler.resume();
846 mBluetoothEnabler.resume();
847 }
Brian Muramatsuc28af522012-06-28 14:25:14 -0700848
Gilles Debunnee78c1872011-06-20 15:00:07 -0700849 public void pause() {
850 mWifiEnabler.pause();
851 mBluetoothEnabler.pause();
852 }
853 }
854
855 @Override
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700856 public void onHeaderClick(Header header, int position) {
857 boolean revert = false;
858 if (header.id == R.id.account_add) {
859 revert = true;
860 }
861
862 super.onHeaderClick(header, position);
863
864 if (revert && mLastHeader != null) {
865 highlightHeader((int) mLastHeader.id);
866 } else {
867 mLastHeader = header;
868 }
869 }
870
871 @Override
Amith Yamasania4379d62011-07-22 10:34:58 -0700872 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
873 // Override the fragment title for Wallpaper settings
Amith Yamasanidfb65432011-11-29 16:38:14 -0800874 int titleRes = pref.getTitleRes();
Amith Yamasania4379d62011-07-22 10:34:58 -0700875 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
Amith Yamasanidfb65432011-11-29 16:38:14 -0800876 titleRes = R.string.wallpaper_settings_fragment_title;
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700877 } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
878 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
Amith Yamasanib0171712013-04-28 22:13:22 -0700879 if (UserManager.get(this).isLinkedUser()) {
880 titleRes = R.string.profile_info_settings_title;
881 } else {
882 titleRes = R.string.user_info_settings_title;
883 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700884 }
Jean Chalard7dabe452012-05-10 18:08:07 +0900885 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
886 null, 0);
Amith Yamasania4379d62011-07-22 10:34:58 -0700887 return true;
888 }
889
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400890 @Override
Amith Yamasani3d384f42012-05-11 15:22:04 -0700891 public boolean shouldUpRecreateTask(Intent targetIntent) {
892 return super.shouldUpRecreateTask(new Intent(this, Settings.class));
893 }
894
Amith Yamasania4379d62011-07-22 10:34:58 -0700895 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700896 public void setListAdapter(ListAdapter adapter) {
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700897 if (adapter == null) {
898 super.setListAdapter(null);
899 } else {
900 super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700901 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700902 }
903
Amith Yamasani56821db2012-06-05 13:20:45 -0700904 @Override
905 public void onAccountsUpdated(Account[] accounts) {
Jeff Sharkey9ff79c12012-10-03 16:48:17 -0700906 // TODO: watch for package upgrades to invalidate cache; see 7206643
907 mAuthenticatorHelper.updateAuthDescriptions(this);
Amith Yamasani56821db2012-06-05 13:20:45 -0700908 mAuthenticatorHelper.onAccountsUpdated(this, accounts);
909 invalidateHeaders();
910 }
911
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700912 /*
913 * Settings subclasses for launching independently.
914 */
Gilles Debunnee78c1872011-06-20 15:00:07 -0700915 public static class BluetoothSettingsActivity extends Settings { /* empty */ }
916 public static class WirelessSettingsActivity extends Settings { /* empty */ }
917 public static class TetherSettingsActivity extends Settings { /* empty */ }
918 public static class VpnSettingsActivity extends Settings { /* empty */ }
919 public static class DateTimeSettingsActivity extends Settings { /* empty */ }
920 public static class StorageSettingsActivity extends Settings { /* empty */ }
921 public static class WifiSettingsActivity extends Settings { /* empty */ }
repo syncb98463f2011-06-30 10:58:43 -0700922 public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700923 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
Jeff Browne46c5f32012-04-05 11:42:18 -0700924 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700925 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
satoke077d2b2011-07-25 09:38:11 +0900926 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700927 public static class LocalePickerActivity extends Settings { /* empty */ }
928 public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
929 public static class SoundSettingsActivity extends Settings { /* empty */ }
930 public static class DisplaySettingsActivity extends Settings { /* empty */ }
931 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
932 public static class ApplicationSettingsActivity extends Settings { /* empty */ }
933 public static class ManageApplicationsActivity extends Settings { /* empty */ }
Dianne Hackborna522a8e2013-01-15 19:02:05 -0800934 public static class AppOpsSummaryActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700935 public static class StorageUseActivity extends Settings { /* empty */ }
936 public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
937 public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
938 public static class SecuritySettingsActivity extends Settings { /* empty */ }
Gilles Debunnea6a8a142011-06-09 11:56:17 -0700939 public static class LocationSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700940 public static class PrivacySettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700941 public static class RunningServicesActivity extends Settings { /* empty */ }
942 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
943 public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
944 public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
945 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
946 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
947 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
948 public static class DataUsageSummaryActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700949 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700950 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
Jeff Hamilton3d670de2011-09-21 16:44:36 -0500951 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
Jeff Brown9e143f52012-09-19 20:46:07 -0700952 public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
Daniel Sandler7dee75c2012-11-27 22:41:30 -0500953 public static class DreamSettingsActivity extends Settings { /* empty */ }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500954 public static class NotificationStationActivity extends Settings { /* empty */ }
Amith Yamasani233592b2013-03-01 17:05:23 -0800955 public static class UserSettingsActivity extends Settings { /* empty */ }
Daniel Sandler79b9bfe2013-04-04 14:30:04 -0400956 public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
Amith Yamasania677ee22013-07-26 13:38:41 -0700957 public static class UsbSettingsActivity extends Settings { /* empty */ }
Martijn Coenen26515da2013-08-01 18:13:33 -0700958 public static class NfcPaymentActivity extends Settings { /* empty */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800959}