blob: 35fe885c56ee1f85e67db40f90a33c74c870d87c [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
Amith Yamasani56821db2012-06-05 13:20:45 -070019import android.accounts.Account;
20import android.accounts.AccountManager;
21import android.accounts.OnAccountsUpdateListener;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090022import android.content.BroadcastReceiver;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080023import android.content.ComponentName;
Gilles Debunnee78c1872011-06-20 15:00:07 -070024import android.content.Context;
Amith Yamasani379d9b02010-09-27 12:03:59 -070025import android.content.Intent;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090026import android.content.IntentFilter;
Dianne Hackborncaefa9b2012-10-10 15:05:42 -070027import android.content.SharedPreferences;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070028import android.content.pm.ActivityInfo;
29import android.content.pm.PackageManager;
30import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070031import android.graphics.drawable.Drawable;
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -070032import android.os.Bundle;
Jeff Sharkey34e964d2012-04-21 15:41:48 -070033import android.os.INetworkManagementService;
34import android.os.RemoteException;
35import android.os.ServiceManager;
Dianne Hackbornbb06a422012-08-16 11:01:57 -070036import android.os.UserHandle;
Jeff Sharkey44202462012-09-19 13:13:45 -070037import android.os.UserManager;
Amith Yamasania4379d62011-07-22 10:34:58 -070038import android.preference.Preference;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070039import android.preference.PreferenceActivity;
Amith Yamasania4379d62011-07-22 10:34:58 -070040import android.preference.PreferenceFragment;
Gilles Debunnee78c1872011-06-20 15:00:07 -070041import android.text.TextUtils;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080042import android.util.Log;
Gilles Debunnee78c1872011-06-20 15:00:07 -070043import android.view.LayoutInflater;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080044import android.view.View;
45import android.view.View.OnClickListener;
Gilles Debunnee78c1872011-06-20 15:00:07 -070046import android.view.ViewGroup;
47import android.widget.ArrayAdapter;
Amith Yamasani9e3a4702011-01-11 09:09:26 -080048import android.widget.Button;
Gilles Debunnee78c1872011-06-20 15:00:07 -070049import android.widget.ImageView;
50import android.widget.ListAdapter;
51import android.widget.Switch;
52import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080053
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080054import com.android.internal.util.ArrayUtils;
Amith Yamasania677ee22013-07-26 13:38:41 -070055import com.android.settings.accessibility.AccessibilitySettings;
Alan Viverette341ff662013-07-18 17:49:33 -070056import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080057import com.android.settings.accounts.AccountSyncSettings;
58import com.android.settings.accounts.AuthenticatorHelper;
59import com.android.settings.accounts.ManageAccountsSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070060import com.android.settings.applications.AppOpsSummary;
61import com.android.settings.applications.ManageApplications;
Dianne Hackbornc6d658e2013-08-08 12:57:53 -070062import com.android.settings.applications.ProcessStatsUi;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080063import com.android.settings.bluetooth.BluetoothEnabler;
64import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070065import com.android.settings.deviceinfo.Memory;
66import com.android.settings.deviceinfo.UsbSettings;
67import com.android.settings.fuelgauge.PowerUsageSummary;
68import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
69import com.android.settings.inputmethod.SpellCheckersSettings;
70import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070071import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070072import com.android.settings.nfc.AndroidBeam;
Martijn Coenen53083ab2013-08-09 13:37:38 -070073import com.android.settings.nfc.PaymentSettings;
Svetoslav2d531652013-09-03 21:32:40 -070074import com.android.settings.print.PrintServiceSettingsFragment;
75import com.android.settings.print.PrintSettingsFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070076import com.android.settings.tts.TextToSpeechSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070077import com.android.settings.users.UserSettings;
78import com.android.settings.vpn2.VpnSettings;
Jeff Sharkey0c3634c2013-02-20 12:35:16 -080079import com.android.settings.wfd.WifiDisplaySettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070080import com.android.settings.wifi.AdvancedWifiSettings;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080081import com.android.settings.wifi.WifiEnabler;
82import com.android.settings.wifi.WifiSettings;
83import com.android.settings.wifi.p2p.WifiP2pSettings;
84
Gilles Debunnee78c1872011-06-20 15:00:07 -070085import java.util.ArrayList;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070086import java.util.Collections;
87import java.util.Comparator;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070088import java.util.HashMap;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070089import java.util.List;
Amith Yamasanid7993472010-08-18 13:59:28 -070090
91/**
92 * Top-level settings activity to handle single pane and double pane UI layout.
93 */
Amith Yamasani56821db2012-06-05 13:20:45 -070094public class Settings extends PreferenceActivity
95 implements ButtonBarHandler, OnAccountsUpdateListener {
Amith Yamasanid7993472010-08-18 13:59:28 -070096
Gilles Debunnee78c1872011-06-20 15:00:07 -070097 private static final String LOG_TAG = "Settings";
Amith Yamasaniea7b28c2012-06-20 13:51:40 -070098
Amith Yamasani5203bdf2010-11-04 09:59:44 -070099 private static final String META_DATA_KEY_HEADER_ID =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700100 "com.android.settings.TOP_LEVEL_HEADER_ID";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700101 private static final String META_DATA_KEY_FRAGMENT_CLASS =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700102 "com.android.settings.FRAGMENT_CLASS";
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800103 private static final String META_DATA_KEY_PARENT_TITLE =
104 "com.android.settings.PARENT_FRAGMENT_TITLE";
105 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
106 "com.android.settings.PARENT_FRAGMENT_CLASS";
107
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800108 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700109
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800110 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
111 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700112
113 private String mFragmentClass;
114 private int mTopLevelHeaderId;
Amith Yamasani3965ae62010-11-15 14:45:19 -0800115 private Header mFirstHeader;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800116 private Header mCurrentHeader;
117 private Header mParentHeader;
118 private boolean mInLocalHeaderSwitch;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700119
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700120 // Show only these settings for restricted users
121 private int[] SETTINGS_FOR_RESTRICTED = {
Amith Yamasani32630392012-08-10 19:31:39 -0700122 R.id.wireless_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700123 R.id.wifi_settings,
124 R.id.bluetooth_settings,
Jeff Sharkey38305fb2012-09-14 16:26:51 -0700125 R.id.data_usage_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700126 R.id.wireless_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700127 R.id.device_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700128 R.id.sound_settings,
129 R.id.display_settings,
Jeff Sharkey90c8b202012-08-30 15:20:10 -0700130 R.id.storage_settings,
Dianne Hackborn271c8b02012-08-20 17:24:39 -0700131 R.id.application_settings,
Dianne Hackborn52e56a22012-09-12 17:02:23 -0700132 R.id.battery_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700133 R.id.personal_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700134 R.id.location_settings,
Amith Yamasani3deeeb72012-04-05 14:44:48 -0700135 R.id.security_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700136 R.id.language_settings,
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700137 R.id.user_settings,
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700138 R.id.account_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700139 R.id.account_add,
140 R.id.system_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700141 R.id.date_time_settings,
Jeff Brown9e143f52012-09-19 20:46:07 -0700142 R.id.about_settings,
Svetoslav Ganovd4c7b492013-06-11 21:15:11 -0700143 R.id.accessibility_settings,
Martijn Coenen26515da2013-08-01 18:13:33 -0700144 R.id.print_settings,
145 R.id.nfc_payment_settings
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700146 };
147
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700148 private SharedPreferences mDevelopmentPreferences;
149 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
150
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700151 // TODO: Update Call Settings based on airplane mode state.
Amith Yamasanib61cf512010-09-12 08:17:50 -0700152
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700153 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
154
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700155 private AuthenticatorHelper mAuthenticatorHelper;
156 private Header mLastHeader;
Amith Yamasani86708a82012-06-06 20:23:08 -0700157 private boolean mListeningToAccountUpdates;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700158
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900159 private boolean mBatteryPresent = true;
160 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
161
162 @Override
163 public void onReceive(Context context, Intent intent) {
164 String action = intent.getAction();
165 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
166 boolean batteryPresent = Utils.isBatteryPresent(intent);
167
168 if (mBatteryPresent != batteryPresent) {
169 mBatteryPresent = batteryPresent;
170 invalidateHeaders();
171 }
172 }
173 }
174 };
175
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700176 @Override
177 protected void onCreate(Bundle savedInstanceState) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800178 if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
179 getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
Jeff Sharkey54d0af52011-08-11 18:26:57 -0700180 }
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700181
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700182 mAuthenticatorHelper = new AuthenticatorHelper();
183 mAuthenticatorHelper.updateAuthDescriptions(this);
184 mAuthenticatorHelper.onAccountsUpdated(this, null);
185
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700186 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
187 Context.MODE_PRIVATE);
188
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700189 getMetaData();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800190 mInLocalHeaderSwitch = true;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700191 super.onCreate(savedInstanceState);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800192 mInLocalHeaderSwitch = false;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700193
Gilles Debunne3661b622011-06-27 11:19:16 -0700194 if (!onIsHidingHeaders() && onIsMultiPane()) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700195 highlightHeader(mTopLevelHeaderId);
Amith Yamasani72aa19d2010-12-09 06:07:12 -0800196 // Force the title so that it doesn't get overridden by a direct launch of
197 // a specific settings screen.
198 setTitle(R.string.settings_label);
199 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800200
201 // Retrieve any saved state
202 if (savedInstanceState != null) {
203 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
204 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
205 }
206
207 // If the current header was saved, switch to it
208 if (savedInstanceState != null && mCurrentHeader != null) {
209 //switchToHeaderLocal(mCurrentHeader);
210 showBreadCrumbs(mCurrentHeader.title, null);
211 }
212
213 if (mParentHeader != null) {
214 setParentTitle(mParentHeader.title, null, new OnClickListener() {
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400215 @Override
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800216 public void onClick(View v) {
217 switchToParent(mParentHeader.fragment);
218 }
219 });
220 }
Gilles Debunnedc7101f2011-06-27 12:00:49 -0700221
Amith Yamasani3d384f42012-05-11 15:22:04 -0700222 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
223 if (onIsMultiPane()) {
224 getActionBar().setDisplayHomeAsUpEnabled(false);
225 getActionBar().setHomeButtonEnabled(false);
226 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800227 }
228
229 @Override
230 protected void onSaveInstanceState(Bundle outState) {
231 super.onSaveInstanceState(outState);
232
233 // Save the current fragment, if it is the same as originally launched
234 if (mCurrentHeader != null) {
235 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
236 }
237 if (mParentHeader != null) {
238 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
239 }
240 }
241
Gilles Debunnee78c1872011-06-20 15:00:07 -0700242 @Override
243 public void onResume() {
244 super.onResume();
245
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700246 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
247 @Override
248 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
249 invalidateHeaders();
250 }
251 };
252 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
253 mDevelopmentPreferencesListener);
254
Gilles Debunnee78c1872011-06-20 15:00:07 -0700255 ListAdapter listAdapter = getListAdapter();
256 if (listAdapter instanceof HeaderAdapter) {
257 ((HeaderAdapter) listAdapter).resume();
258 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700259 invalidateHeaders();
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900260
261 registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700262 }
263
264 @Override
265 public void onPause() {
266 super.onPause();
267
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900268 unregisterReceiver(mBatteryInfoReceiver);
269
Gilles Debunnee78c1872011-06-20 15:00:07 -0700270 ListAdapter listAdapter = getListAdapter();
271 if (listAdapter instanceof HeaderAdapter) {
272 ((HeaderAdapter) listAdapter).pause();
Amith Yamasani86708a82012-06-06 20:23:08 -0700273 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700274
275 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
276 mDevelopmentPreferencesListener);
277 mDevelopmentPreferencesListener = null;
Amith Yamasani86708a82012-06-06 20:23:08 -0700278 }
279
280 @Override
281 public void onDestroy() {
282 super.onDestroy();
283 if (mListeningToAccountUpdates) {
Amith Yamasani56821db2012-06-05 13:20:45 -0700284 AccountManager.get(this).removeOnAccountsUpdatedListener(this);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700285 }
286 }
287
Amith Yamasani56f51a82013-08-05 10:07:23 -0700288 @Override
289 public boolean onIsMultiPane() {
290 return false;
291 }
292
Amith Yamasania677ee22013-07-26 13:38:41 -0700293 private static final String[] ENTRY_FRAGMENTS = {
294 WirelessSettings.class.getName(),
295 WifiSettings.class.getName(),
296 AdvancedWifiSettings.class.getName(),
297 BluetoothSettings.class.getName(),
298 TetherSettings.class.getName(),
299 WifiP2pSettings.class.getName(),
300 VpnSettings.class.getName(),
301 DateTimeSettings.class.getName(),
302 LocalePicker.class.getName(),
303 InputMethodAndLanguageSettings.class.getName(),
304 SpellCheckersSettings.class.getName(),
305 UserDictionaryList.class.getName(),
306 UserDictionarySettings.class.getName(),
307 SoundSettings.class.getName(),
308 DisplaySettings.class.getName(),
309 DeviceInfoSettings.class.getName(),
310 ManageApplications.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700311 ProcessStatsUi.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700312 NotificationStation.class.getName(),
313 AppOpsSummary.class.getName(),
314 LocationSettings.class.getName(),
315 SecuritySettings.class.getName(),
316 PrivacySettings.class.getName(),
317 DeviceAdminSettings.class.getName(),
318 AccessibilitySettings.class.getName(),
319 TextToSpeechSettings.class.getName(),
320 Memory.class.getName(),
321 DevelopmentSettings.class.getName(),
322 UsbSettings.class.getName(),
323 AndroidBeam.class.getName(),
324 WifiDisplaySettings.class.getName(),
325 PowerUsageSummary.class.getName(),
326 AccountSyncSettings.class.getName(),
327 CryptKeeperSettings.class.getName(),
328 DataUsageSummary.class.getName(),
329 DreamSettings.class.getName(),
330 UserSettings.class.getName(),
331 NotificationAccessSettings.class.getName(),
Amith Yamasaniee226f92013-08-05 11:02:16 -0700332 ManageAccountsSettings.class.getName(),
Svetoslav2d531652013-09-03 21:32:40 -0700333 PrintSettingsFragment.class.getName(),
Martijn Coenen53083ab2013-08-09 13:37:38 -0700334 TrustedCredentialsSettings.class.getName(),
335 PaymentSettings.class.getName()
Amith Yamasania677ee22013-07-26 13:38:41 -0700336 };
337
338 @Override
339 protected boolean isValidFragment(String fragmentName) {
340 // Almost all fragments are wrapped in this,
341 // except for a few that have their own activities.
342 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
343 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
344 }
345 return false;
346 }
347
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800348 private void switchToHeaderLocal(Header header) {
349 mInLocalHeaderSwitch = true;
350 switchToHeader(header);
351 mInLocalHeaderSwitch = false;
352 }
353
354 @Override
355 public void switchToHeader(Header header) {
356 if (!mInLocalHeaderSwitch) {
357 mCurrentHeader = null;
358 mParentHeader = null;
359 }
360 super.switchToHeader(header);
361 }
362
363 /**
364 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800365 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800366 */
367 private void switchToParent(String className) {
368 final ComponentName cn = new ComponentName(this, className);
369 try {
370 final PackageManager pm = getPackageManager();
371 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
372
373 if (parentInfo != null && parentInfo.metaData != null) {
374 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
375 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
376 Header parentHeader = new Header();
377 parentHeader.fragment = fragmentClass;
378 parentHeader.title = fragmentTitle;
379 mCurrentHeader = parentHeader;
380
381 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700382 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800383
384 mParentHeader = new Header();
385 mParentHeader.fragment
386 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
387 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
388 }
389 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700390 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800391 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700392 }
393
Amith Yamasani3965ae62010-11-15 14:45:19 -0800394 @Override
395 public void onNewIntent(Intent intent) {
396 super.onNewIntent(intent);
397
398 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700399 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
400 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
401 switchToHeaderLocal(mFirstHeader);
402 }
403 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800404 }
405 }
406
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700407 private void highlightHeader(int id) {
408 if (id != 0) {
409 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700410 if (index != null) {
411 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700412 if (isMultiPane()) {
413 getListView().smoothScrollToPosition(index);
414 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700415 }
416 }
417 }
418
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700419 @Override
420 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700421 Intent superIntent = super.getIntent();
422 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700423 // This is called from super.onCreate, isMultiPane() is not yet reliable
424 // Do not use onIsHidingHeaders either, which relies itself on this method
425 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700426 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700427 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700428 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700429 if (args != null) {
430 args = new Bundle(args);
431 } else {
432 args = new Bundle();
433 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700434 args.putParcelable("intent", superIntent);
435 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700436 return modIntent;
437 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700438 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700439 }
440
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700441 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700442 * Checks if the component name in the intent is different from the Settings class and
443 * returns the class name to load as a fragment.
444 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700445 protected String getStartingFragmentClass(Intent intent) {
446 if (mFragmentClass != null) return mFragmentClass;
447
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700448 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700449 if (intentClass.equals(getClass().getName())) return null;
450
Dianne Hackbornee293792010-11-01 12:32:33 -0700451 if ("com.android.settings.ManageApplications".equals(intentClass)
452 || "com.android.settings.RunningServices".equals(intentClass)
453 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700454 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700455 intentClass = com.android.settings.applications.ManageApplications.class.getName();
456 }
457
Amith Yamasani379d9b02010-09-27 12:03:59 -0700458 return intentClass;
459 }
460
461 /**
462 * Override initial header when an activity-alias is causing Settings to be launched
463 * for a specific fragment encoded in the android:name parameter.
464 */
465 @Override
466 public Header onGetInitialHeader() {
467 String fragmentClass = getStartingFragmentClass(super.getIntent());
468 if (fragmentClass != null) {
469 Header header = new Header();
470 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800471 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700472 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800473 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700474 return header;
475 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700476
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700477 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700478 }
479
Dianne Hackbornb7258182011-03-15 16:23:55 -0700480 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700481 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
482 int titleRes, int shortTitleRes) {
483 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
484 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700485
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800486 // Some fragments want split ActionBar; these should stay in sync with
487 // uiOptions for fragments also defined as activities in manifest.
488 if (WifiSettings.class.getName().equals(fragmentName) ||
489 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800490 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800491 BluetoothSettings.class.getName().equals(fragmentName) ||
492 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700493 LocationSettings.class.getName().equals(fragmentName) ||
Svetoslav2d531652013-09-03 21:32:40 -0700494 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName) ||
495 PrintSettingsFragment.class.getName().equals(fragmentName) ||
496 PrintServiceSettingsFragment.class.getName().equals(fragmentName)) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800497 intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700498 }
499
Dianne Hackbornb7258182011-03-15 16:23:55 -0700500 intent.setClass(this, SubSettings.class);
501 return intent;
502 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700503
Amith Yamasani379d9b02010-09-27 12:03:59 -0700504 /**
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700505 * Populate the activity with the top-level headers.
506 */
Amith Yamasanid7993472010-08-18 13:59:28 -0700507 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700508 public void onBuildHeaders(List<Header> headers) {
509 loadHeadersFromResource(R.xml.settings_headers, headers);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700510 updateHeaderList(headers);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700511 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700512
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700513 private void updateHeaderList(List<Header> target) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700514 final boolean showDev = mDevelopmentPreferences.getBoolean(
515 DevelopmentSettings.PREF_SHOW,
516 android.os.Build.TYPE.equals("eng"));
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700517 int i = 0;
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400518
519 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700520 mHeaderIndexMap.clear();
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700521 while (i < target.size()) {
522 Header header = target.get(i);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700523 // Ids are integers, so downcasting
524 int id = (int) header.id;
Chris Wren2bc32ae2012-09-24 14:23:46 -0400525 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700526 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
Gilles Debunne2454f492011-06-21 16:16:06 -0700527 } else if (id == R.id.wifi_settings) {
528 // Remove WiFi Settings if WiFi service is not available.
529 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700530 target.remove(i);
Gilles Debunne2454f492011-06-21 16:16:06 -0700531 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700532 } else if (id == R.id.bluetooth_settings) {
533 // Remove Bluetooth Settings if Bluetooth service is not available.
Gilles Debunne2454f492011-06-21 16:16:06 -0700534 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700535 target.remove(i);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700536 }
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700537 } else if (id == R.id.data_usage_settings) {
538 // Remove data usage when kernel module not enabled
539 final INetworkManagementService netManager = INetworkManagementService.Stub
540 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
541 try {
542 if (!netManager.isBandwidthControlEnabled()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700543 target.remove(i);
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700544 }
545 } catch (RemoteException e) {
546 // ignored
547 }
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900548 } else if (id == R.id.battery_settings) {
549 // Remove battery settings when battery is not available. (e.g. TV)
550
551 if (!mBatteryPresent) {
552 target.remove(i);
553 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700554 } else if (id == R.id.account_settings) {
555 int headerIndex = i + 1;
556 i = insertAccountsHeaders(target, headerIndex);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700557 } else if (id == R.id.user_settings) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700558 if (!UserHandle.MU_ENABLED
Jeff Sharkey44202462012-09-19 13:13:45 -0700559 || !UserManager.supportsMultipleUsers()
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700560 || Utils.isMonkeyRunning()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700561 target.remove(i);
562 }
Martijn Coenen26515da2013-08-01 18:13:33 -0700563 } else if (id == R.id.nfc_payment_settings) {
564 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
565 target.remove(i);
566 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700567 } else if (id == R.id.development_settings) {
568 if (!showDev) {
569 target.remove(i);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700570 }
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400571 } else if (id == R.id.account_add) {
572 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
573 target.remove(i);
574 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700575 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700576
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900577 if (i < target.size() && target.get(i) == header
Amith Yamasanib99f8642012-10-10 21:41:12 -0700578 && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700579 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700580 target.remove(i);
Amith Yamasanid7993472010-08-18 13:59:28 -0700581 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700582
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700583 // Increment if the current one wasn't removed by the Utils code.
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900584 if (i < target.size() && target.get(i) == header) {
Amith Yamasani3965ae62010-11-15 14:45:19 -0800585 // Hold on to the first header, when we need to reset to the top-level
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700586 if (mFirstHeader == null &&
587 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
588 mFirstHeader = header;
589 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700590 mHeaderIndexMap.put(id, i);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700591 i++;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700592 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700593 }
594 }
595
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700596 private int insertAccountsHeaders(List<Header> target, int headerIndex) {
597 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
598 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
599 for (String accountType : accountTypes) {
600 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
Brian Muramatsuc28af522012-06-28 14:25:14 -0700601 if (label == null) {
602 continue;
603 }
604
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700605 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
606 boolean skipToAccount = accounts.length == 1
607 && !mAuthenticatorHelper.hasAccountPreferences(accountType);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700608 Header accHeader = new Header();
609 accHeader.title = label;
610 if (accHeader.extras == null) {
611 accHeader.extras = new Bundle();
612 }
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700613 if (skipToAccount) {
614 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
615 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
616 accHeader.fragment = AccountSyncSettings.class.getName();
617 accHeader.fragmentArguments = new Bundle();
618 // Need this for the icon
619 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
620 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
621 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
622 accounts[0]);
623 } else {
624 accHeader.breadCrumbTitle = label;
625 accHeader.breadCrumbShortTitle = label;
626 accHeader.fragment = ManageAccountsSettings.class.getName();
627 accHeader.fragmentArguments = new Bundle();
628 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
629 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
630 accountType);
631 if (!isMultiPane()) {
632 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
633 label.toString());
634 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700635 }
636 accountHeaders.add(accHeader);
637 }
638
639 // Sort by label
640 Collections.sort(accountHeaders, new Comparator<Header>() {
641 @Override
642 public int compare(Header h1, Header h2) {
643 return h1.title.toString().compareTo(h2.title.toString());
644 }
645 });
646
647 for (Header header : accountHeaders) {
648 target.add(headerIndex++, header);
649 }
Amith Yamasani86708a82012-06-06 20:23:08 -0700650 if (!mListeningToAccountUpdates) {
651 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
652 mListeningToAccountUpdates = true;
653 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700654 return headerIndex;
655 }
656
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700657 private void getMetaData() {
658 try {
659 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
660 PackageManager.GET_META_DATA);
661 if (ai == null || ai.metaData == null) return;
662 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
663 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700664
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800665 // Check if it has a parent specified and create a Header object
666 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
667 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
668 if (parentFragmentClass != null) {
669 mParentHeader = new Header();
670 mParentHeader.fragment = parentFragmentClass;
671 if (parentHeaderTitleRes != 0) {
672 mParentHeader.title = getResources().getString(parentHeaderTitleRes);
673 }
674 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700675 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700676 // No recovery
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700677 }
678 }
679
Amith Yamasani9e3a4702011-01-11 09:09:26 -0800680 @Override
681 public boolean hasNextButton() {
682 return super.hasNextButton();
683 }
684
685 @Override
686 public Button getNextButton() {
687 return super.getNextButton();
688 }
689
Gilles Debunnee78c1872011-06-20 15:00:07 -0700690 private static class HeaderAdapter extends ArrayAdapter<Header> {
691 static final int HEADER_TYPE_CATEGORY = 0;
692 static final int HEADER_TYPE_NORMAL = 1;
693 static final int HEADER_TYPE_SWITCH = 2;
694 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
695
696 private final WifiEnabler mWifiEnabler;
697 private final BluetoothEnabler mBluetoothEnabler;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700698 private AuthenticatorHelper mAuthHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700699
700 private static class HeaderViewHolder {
701 ImageView icon;
702 TextView title;
703 TextView summary;
704 Switch switch_;
705 }
706
707 private LayoutInflater mInflater;
708
709 static int getHeaderType(Header header) {
710 if (header.fragment == null && header.intent == null) {
711 return HEADER_TYPE_CATEGORY;
712 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
713 return HEADER_TYPE_SWITCH;
714 } else {
715 return HEADER_TYPE_NORMAL;
716 }
717 }
718
719 @Override
720 public int getItemViewType(int position) {
721 Header header = getItem(position);
722 return getHeaderType(header);
723 }
724
725 @Override
726 public boolean areAllItemsEnabled() {
727 return false; // because of categories
728 }
729
730 @Override
731 public boolean isEnabled(int position) {
732 return getItemViewType(position) != HEADER_TYPE_CATEGORY;
733 }
734
735 @Override
736 public int getViewTypeCount() {
737 return HEADER_TYPE_COUNT;
738 }
739
740 @Override
741 public boolean hasStableIds() {
742 return true;
743 }
744
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700745 public HeaderAdapter(Context context, List<Header> objects,
746 AuthenticatorHelper authenticatorHelper) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700747 super(context, 0, objects);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700748
749 mAuthHelper = authenticatorHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700750 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700751
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700752 // Temp Switches provided as placeholder until the adapter replaces these with actual
Gilles Debunnee78c1872011-06-20 15:00:07 -0700753 // Switches inflated from their layouts. Must be done before adapter is set in super
754 mWifiEnabler = new WifiEnabler(context, new Switch(context));
755 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
756 }
757
758 @Override
759 public View getView(int position, View convertView, ViewGroup parent) {
760 HeaderViewHolder holder;
761 Header header = getItem(position);
762 int headerType = getHeaderType(header);
763 View view = null;
764
765 if (convertView == null) {
766 holder = new HeaderViewHolder();
767 switch (headerType) {
768 case HEADER_TYPE_CATEGORY:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700769 view = new TextView(getContext(), null,
770 android.R.attr.listSeparatorTextViewStyle);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700771 holder.title = (TextView) view;
772 break;
773
774 case HEADER_TYPE_SWITCH:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700775 view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
776 false);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700777 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700778 holder.title = (TextView)
779 view.findViewById(com.android.internal.R.id.title);
780 holder.summary = (TextView)
781 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700782 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
783 break;
784
785 case HEADER_TYPE_NORMAL:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700786 view = mInflater.inflate(
Amith Yamasanic8a93172012-06-08 13:35:47 -0700787 R.layout.preference_header_item, parent,
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700788 false);
Amith Yamasanic8a93172012-06-08 13:35:47 -0700789 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700790 holder.title = (TextView)
791 view.findViewById(com.android.internal.R.id.title);
792 holder.summary = (TextView)
793 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700794 break;
795 }
796 view.setTag(holder);
797 } else {
798 view = convertView;
799 holder = (HeaderViewHolder) view.getTag();
800 }
801
802 // All view fields must be updated every time, because the view may be recycled
803 switch (headerType) {
804 case HEADER_TYPE_CATEGORY:
805 holder.title.setText(header.getTitle(getContext().getResources()));
806 break;
807
808 case HEADER_TYPE_SWITCH:
809 // Would need a different treatment if the main menu had more switches
810 if (header.id == R.id.wifi_settings) {
811 mWifiEnabler.setSwitch(holder.switch_);
812 } else {
813 mBluetoothEnabler.setSwitch(holder.switch_);
814 }
815 // No break, fall through on purpose to update common fields
816
817 //$FALL-THROUGH$
818 case HEADER_TYPE_NORMAL:
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700819 if (header.extras != null
820 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700821 String accType = header.extras.getString(
822 ManageAccountsSettings.KEY_ACCOUNT_TYPE);
823 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
824 lp.width = getContext().getResources().getDimensionPixelSize(
825 R.dimen.header_icon_width);
826 lp.height = lp.width;
827 holder.icon.setLayoutParams(lp);
828 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
829 holder.icon.setImageDrawable(icon);
830 } else {
831 holder.icon.setImageResource(header.iconRes);
832 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700833 holder.title.setText(header.getTitle(getContext().getResources()));
834 CharSequence summary = header.getSummary(getContext().getResources());
835 if (!TextUtils.isEmpty(summary)) {
836 holder.summary.setVisibility(View.VISIBLE);
837 holder.summary.setText(summary);
838 } else {
839 holder.summary.setVisibility(View.GONE);
840 }
841 break;
842 }
843
844 return view;
845 }
846
847 public void resume() {
848 mWifiEnabler.resume();
849 mBluetoothEnabler.resume();
850 }
Brian Muramatsuc28af522012-06-28 14:25:14 -0700851
Gilles Debunnee78c1872011-06-20 15:00:07 -0700852 public void pause() {
853 mWifiEnabler.pause();
854 mBluetoothEnabler.pause();
855 }
856 }
857
858 @Override
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700859 public void onHeaderClick(Header header, int position) {
860 boolean revert = false;
861 if (header.id == R.id.account_add) {
862 revert = true;
863 }
864
865 super.onHeaderClick(header, position);
866
867 if (revert && mLastHeader != null) {
868 highlightHeader((int) mLastHeader.id);
869 } else {
870 mLastHeader = header;
871 }
872 }
873
874 @Override
Amith Yamasania4379d62011-07-22 10:34:58 -0700875 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
876 // Override the fragment title for Wallpaper settings
Amith Yamasanidfb65432011-11-29 16:38:14 -0800877 int titleRes = pref.getTitleRes();
Amith Yamasania4379d62011-07-22 10:34:58 -0700878 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
Amith Yamasanidfb65432011-11-29 16:38:14 -0800879 titleRes = R.string.wallpaper_settings_fragment_title;
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700880 } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
881 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
Amith Yamasanib0171712013-04-28 22:13:22 -0700882 if (UserManager.get(this).isLinkedUser()) {
883 titleRes = R.string.profile_info_settings_title;
884 } else {
885 titleRes = R.string.user_info_settings_title;
886 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700887 }
Jean Chalard7dabe452012-05-10 18:08:07 +0900888 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
889 null, 0);
Amith Yamasania4379d62011-07-22 10:34:58 -0700890 return true;
891 }
892
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400893 @Override
Amith Yamasani3d384f42012-05-11 15:22:04 -0700894 public boolean shouldUpRecreateTask(Intent targetIntent) {
895 return super.shouldUpRecreateTask(new Intent(this, Settings.class));
896 }
897
Amith Yamasania4379d62011-07-22 10:34:58 -0700898 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700899 public void setListAdapter(ListAdapter adapter) {
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700900 if (adapter == null) {
901 super.setListAdapter(null);
902 } else {
903 super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700904 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700905 }
906
Amith Yamasani56821db2012-06-05 13:20:45 -0700907 @Override
908 public void onAccountsUpdated(Account[] accounts) {
Jeff Sharkey9ff79c12012-10-03 16:48:17 -0700909 // TODO: watch for package upgrades to invalidate cache; see 7206643
910 mAuthenticatorHelper.updateAuthDescriptions(this);
Amith Yamasani56821db2012-06-05 13:20:45 -0700911 mAuthenticatorHelper.onAccountsUpdated(this, accounts);
912 invalidateHeaders();
913 }
914
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700915 /*
916 * Settings subclasses for launching independently.
917 */
Gilles Debunnee78c1872011-06-20 15:00:07 -0700918 public static class BluetoothSettingsActivity extends Settings { /* empty */ }
919 public static class WirelessSettingsActivity extends Settings { /* empty */ }
920 public static class TetherSettingsActivity extends Settings { /* empty */ }
921 public static class VpnSettingsActivity extends Settings { /* empty */ }
922 public static class DateTimeSettingsActivity extends Settings { /* empty */ }
923 public static class StorageSettingsActivity extends Settings { /* empty */ }
924 public static class WifiSettingsActivity extends Settings { /* empty */ }
repo syncb98463f2011-06-30 10:58:43 -0700925 public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700926 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
Jeff Browne46c5f32012-04-05 11:42:18 -0700927 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700928 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
satoke077d2b2011-07-25 09:38:11 +0900929 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700930 public static class LocalePickerActivity extends Settings { /* empty */ }
931 public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
932 public static class SoundSettingsActivity extends Settings { /* empty */ }
933 public static class DisplaySettingsActivity extends Settings { /* empty */ }
934 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
935 public static class ApplicationSettingsActivity extends Settings { /* empty */ }
936 public static class ManageApplicationsActivity extends Settings { /* empty */ }
Dianne Hackborna522a8e2013-01-15 19:02:05 -0800937 public static class AppOpsSummaryActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700938 public static class StorageUseActivity extends Settings { /* empty */ }
939 public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
940 public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
941 public static class SecuritySettingsActivity extends Settings { /* empty */ }
Gilles Debunnea6a8a142011-06-09 11:56:17 -0700942 public static class LocationSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700943 public static class PrivacySettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700944 public static class RunningServicesActivity extends Settings { /* empty */ }
945 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
946 public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
947 public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
948 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
949 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
950 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
951 public static class DataUsageSummaryActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700952 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700953 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
Jeff Hamilton3d670de2011-09-21 16:44:36 -0500954 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
Jeff Brown9e143f52012-09-19 20:46:07 -0700955 public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
Daniel Sandler7dee75c2012-11-27 22:41:30 -0500956 public static class DreamSettingsActivity extends Settings { /* empty */ }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500957 public static class NotificationStationActivity extends Settings { /* empty */ }
Amith Yamasani233592b2013-03-01 17:05:23 -0800958 public static class UserSettingsActivity extends Settings { /* empty */ }
Daniel Sandler79b9bfe2013-04-04 14:30:04 -0400959 public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
Amith Yamasania677ee22013-07-26 13:38:41 -0700960 public static class UsbSettingsActivity extends Settings { /* empty */ }
Geoffrey Borggaardfc6bc202013-08-09 11:44:42 -0400961 public static class TrustedCredentialsSettingsActivity extends Settings { /* empty */ }
Martijn Coenen53083ab2013-08-09 13:37:38 -0700962 public static class PaymentSettingsActivity extends Settings { /* empty */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800963}