blob: a9d35a2ef9ae3484b8c81d78bbfb296a405a9e8a [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
Amith Yamasani56821db2012-06-05 13:20:45 -070019import android.accounts.Account;
20import android.accounts.AccountManager;
21import android.accounts.OnAccountsUpdateListener;
Amith Yamasania677ee22013-07-26 13:38:41 -070022import android.app.Fragment;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090023import android.content.BroadcastReceiver;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080024import android.content.ComponentName;
Gilles Debunnee78c1872011-06-20 15:00:07 -070025import android.content.Context;
Amith Yamasani379d9b02010-09-27 12:03:59 -070026import android.content.Intent;
Jaewan Kima3fe77b2013-06-04 21:17:40 +090027import android.content.IntentFilter;
Amith Yamasani233592b2013-03-01 17:05:23 -080028import android.content.RestrictionEntry;
Dianne Hackborncaefa9b2012-10-10 15:05:42 -070029import android.content.SharedPreferences;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070030import android.content.pm.ActivityInfo;
31import android.content.pm.PackageManager;
32import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070033import android.graphics.drawable.Drawable;
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -070034import android.os.Bundle;
Jeff Sharkey34e964d2012-04-21 15:41:48 -070035import android.os.INetworkManagementService;
36import android.os.RemoteException;
37import android.os.ServiceManager;
Dianne Hackbornbb06a422012-08-16 11:01:57 -070038import android.os.UserHandle;
Jeff Sharkey44202462012-09-19 13:13:45 -070039import android.os.UserManager;
Amith Yamasania4379d62011-07-22 10:34:58 -070040import android.preference.Preference;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070041import android.preference.PreferenceActivity;
Amith Yamasania4379d62011-07-22 10:34:58 -070042import android.preference.PreferenceFragment;
Gilles Debunnee78c1872011-06-20 15:00:07 -070043import android.text.TextUtils;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080044import android.util.Log;
Gilles Debunnee78c1872011-06-20 15:00:07 -070045import android.view.LayoutInflater;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -080046import android.view.View;
47import android.view.View.OnClickListener;
Gilles Debunnee78c1872011-06-20 15:00:07 -070048import android.view.ViewGroup;
49import android.widget.ArrayAdapter;
Amith Yamasani9e3a4702011-01-11 09:09:26 -080050import android.widget.Button;
Gilles Debunnee78c1872011-06-20 15:00:07 -070051import android.widget.ImageView;
52import android.widget.ListAdapter;
53import android.widget.Switch;
54import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080055
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080056import com.android.internal.util.ArrayUtils;
Amith Yamasania677ee22013-07-26 13:38:41 -070057import com.android.settings.accessibility.AccessibilitySettings;
Alan Viverette341ff662013-07-18 17:49:33 -070058import com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment;
Amith Yamasania677ee22013-07-26 13:38:41 -070059import com.android.settings.ChooseLockGeneric.ChooseLockGenericFragment;
60import com.android.settings.ChooseLockPassword.ChooseLockPasswordFragment;
61import com.android.settings.ChooseLockPattern.ChooseLockPatternFragment;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080062import com.android.settings.accounts.AccountSyncSettings;
63import com.android.settings.accounts.AuthenticatorHelper;
64import com.android.settings.accounts.ManageAccountsSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070065import com.android.settings.applications.AppOpsSummary;
66import com.android.settings.applications.ManageApplications;
Dianne Hackbornc6d658e2013-08-08 12:57:53 -070067import com.android.settings.applications.ProcessStatsUi;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080068import com.android.settings.bluetooth.BluetoothEnabler;
69import com.android.settings.bluetooth.BluetoothSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070070import com.android.settings.deviceinfo.Memory;
71import com.android.settings.deviceinfo.UsbSettings;
72import com.android.settings.fuelgauge.PowerUsageSummary;
73import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
74import com.android.settings.inputmethod.SpellCheckersSettings;
75import com.android.settings.inputmethod.UserDictionaryList;
Amith Yamasanie9904202013-08-01 10:26:14 -070076import com.android.settings.location.LocationSettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070077import com.android.settings.nfc.AndroidBeam;
78import com.android.settings.tts.TextToSpeechSettings;
79import com.android.settings.users.AppRestrictionsFragment;
80import com.android.settings.users.UserSettings;
81import com.android.settings.vpn2.VpnSettings;
Jeff Sharkey0c3634c2013-02-20 12:35:16 -080082import com.android.settings.wfd.WifiDisplaySettings;
Amith Yamasania677ee22013-07-26 13:38:41 -070083import com.android.settings.wifi.AdvancedWifiSettings;
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -080084import com.android.settings.wifi.WifiEnabler;
85import com.android.settings.wifi.WifiSettings;
86import com.android.settings.wifi.p2p.WifiP2pSettings;
87
Gilles Debunnee78c1872011-06-20 15:00:07 -070088import java.util.ArrayList;
Amith Yamasanid1ab8282012-05-18 09:50:08 -070089import java.util.Collections;
90import java.util.Comparator;
Amith Yamasani5203bdf2010-11-04 09:59:44 -070091import java.util.HashMap;
Amith Yamasani02cf71a2010-09-21 15:48:52 -070092import java.util.List;
Amith Yamasanid7993472010-08-18 13:59:28 -070093
94/**
95 * Top-level settings activity to handle single pane and double pane UI layout.
96 */
Amith Yamasani56821db2012-06-05 13:20:45 -070097public class Settings extends PreferenceActivity
98 implements ButtonBarHandler, OnAccountsUpdateListener {
Amith Yamasanid7993472010-08-18 13:59:28 -070099
Gilles Debunnee78c1872011-06-20 15:00:07 -0700100 private static final String LOG_TAG = "Settings";
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700101
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700102 private static final String META_DATA_KEY_HEADER_ID =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700103 "com.android.settings.TOP_LEVEL_HEADER_ID";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700104 private static final String META_DATA_KEY_FRAGMENT_CLASS =
Gilles Debunnee78c1872011-06-20 15:00:07 -0700105 "com.android.settings.FRAGMENT_CLASS";
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800106 private static final String META_DATA_KEY_PARENT_TITLE =
107 "com.android.settings.PARENT_FRAGMENT_TITLE";
108 private static final String META_DATA_KEY_PARENT_FRAGMENT_CLASS =
109 "com.android.settings.PARENT_FRAGMENT_CLASS";
110
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800111 private static final String EXTRA_UI_OPTIONS = "settings:ui_options";
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700112
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800113 private static final String SAVE_KEY_CURRENT_HEADER = "com.android.settings.CURRENT_HEADER";
114 private static final String SAVE_KEY_PARENT_HEADER = "com.android.settings.PARENT_HEADER";
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700115
116 private String mFragmentClass;
117 private int mTopLevelHeaderId;
Amith Yamasani3965ae62010-11-15 14:45:19 -0800118 private Header mFirstHeader;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800119 private Header mCurrentHeader;
120 private Header mParentHeader;
121 private boolean mInLocalHeaderSwitch;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700122
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700123 // Show only these settings for restricted users
124 private int[] SETTINGS_FOR_RESTRICTED = {
Amith Yamasani32630392012-08-10 19:31:39 -0700125 R.id.wireless_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700126 R.id.wifi_settings,
127 R.id.bluetooth_settings,
Jeff Sharkey38305fb2012-09-14 16:26:51 -0700128 R.id.data_usage_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700129 R.id.wireless_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700130 R.id.device_section,
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700131 R.id.sound_settings,
132 R.id.display_settings,
Jeff Sharkey90c8b202012-08-30 15:20:10 -0700133 R.id.storage_settings,
Dianne Hackborn271c8b02012-08-20 17:24:39 -0700134 R.id.application_settings,
Dianne Hackborn52e56a22012-09-12 17:02:23 -0700135 R.id.battery_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700136 R.id.personal_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700137 R.id.location_settings,
Amith Yamasani3deeeb72012-04-05 14:44:48 -0700138 R.id.security_settings,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700139 R.id.language_settings,
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700140 R.id.user_settings,
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700141 R.id.account_settings,
Amith Yamasani32630392012-08-10 19:31:39 -0700142 R.id.account_add,
143 R.id.system_section,
Amith Yamasani9627a8e2012-09-23 12:54:14 -0700144 R.id.date_time_settings,
Jeff Brown9e143f52012-09-19 20:46:07 -0700145 R.id.about_settings,
Svetoslav Ganovd4c7b492013-06-11 21:15:11 -0700146 R.id.accessibility_settings,
Martijn Coenen26515da2013-08-01 18:13:33 -0700147 R.id.print_settings,
148 R.id.nfc_payment_settings
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700149 };
150
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700151 private SharedPreferences mDevelopmentPreferences;
152 private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
153
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700154 // TODO: Update Call Settings based on airplane mode state.
Amith Yamasanib61cf512010-09-12 08:17:50 -0700155
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700156 protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
157
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700158 private AuthenticatorHelper mAuthenticatorHelper;
159 private Header mLastHeader;
Amith Yamasani86708a82012-06-06 20:23:08 -0700160 private boolean mListeningToAccountUpdates;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700161
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900162 private boolean mBatteryPresent = true;
163 private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
164
165 @Override
166 public void onReceive(Context context, Intent intent) {
167 String action = intent.getAction();
168 if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
169 boolean batteryPresent = Utils.isBatteryPresent(intent);
170
171 if (mBatteryPresent != batteryPresent) {
172 mBatteryPresent = batteryPresent;
173 invalidateHeaders();
174 }
175 }
176 }
177 };
178
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700179 @Override
180 protected void onCreate(Bundle savedInstanceState) {
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800181 if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
182 getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
Jeff Sharkey54d0af52011-08-11 18:26:57 -0700183 }
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700184
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700185 mAuthenticatorHelper = new AuthenticatorHelper();
186 mAuthenticatorHelper.updateAuthDescriptions(this);
187 mAuthenticatorHelper.onAccountsUpdated(this, null);
188
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700189 mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
190 Context.MODE_PRIVATE);
191
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700192 getMetaData();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800193 mInLocalHeaderSwitch = true;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700194 super.onCreate(savedInstanceState);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800195 mInLocalHeaderSwitch = false;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700196
Gilles Debunne3661b622011-06-27 11:19:16 -0700197 if (!onIsHidingHeaders() && onIsMultiPane()) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700198 highlightHeader(mTopLevelHeaderId);
Amith Yamasani72aa19d2010-12-09 06:07:12 -0800199 // Force the title so that it doesn't get overridden by a direct launch of
200 // a specific settings screen.
201 setTitle(R.string.settings_label);
202 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800203
204 // Retrieve any saved state
205 if (savedInstanceState != null) {
206 mCurrentHeader = savedInstanceState.getParcelable(SAVE_KEY_CURRENT_HEADER);
207 mParentHeader = savedInstanceState.getParcelable(SAVE_KEY_PARENT_HEADER);
208 }
209
210 // If the current header was saved, switch to it
211 if (savedInstanceState != null && mCurrentHeader != null) {
212 //switchToHeaderLocal(mCurrentHeader);
213 showBreadCrumbs(mCurrentHeader.title, null);
214 }
215
216 if (mParentHeader != null) {
217 setParentTitle(mParentHeader.title, null, new OnClickListener() {
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400218 @Override
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800219 public void onClick(View v) {
220 switchToParent(mParentHeader.fragment);
221 }
222 });
223 }
Gilles Debunnedc7101f2011-06-27 12:00:49 -0700224
Amith Yamasani3d384f42012-05-11 15:22:04 -0700225 // Override up navigation for multi-pane, since we handle it in the fragment breadcrumbs
226 if (onIsMultiPane()) {
227 getActionBar().setDisplayHomeAsUpEnabled(false);
228 getActionBar().setHomeButtonEnabled(false);
229 }
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800230 }
231
232 @Override
233 protected void onSaveInstanceState(Bundle outState) {
234 super.onSaveInstanceState(outState);
235
236 // Save the current fragment, if it is the same as originally launched
237 if (mCurrentHeader != null) {
238 outState.putParcelable(SAVE_KEY_CURRENT_HEADER, mCurrentHeader);
239 }
240 if (mParentHeader != null) {
241 outState.putParcelable(SAVE_KEY_PARENT_HEADER, mParentHeader);
242 }
243 }
244
Gilles Debunnee78c1872011-06-20 15:00:07 -0700245 @Override
246 public void onResume() {
247 super.onResume();
248
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700249 mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
250 @Override
251 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
252 invalidateHeaders();
253 }
254 };
255 mDevelopmentPreferences.registerOnSharedPreferenceChangeListener(
256 mDevelopmentPreferencesListener);
257
Gilles Debunnee78c1872011-06-20 15:00:07 -0700258 ListAdapter listAdapter = getListAdapter();
259 if (listAdapter instanceof HeaderAdapter) {
260 ((HeaderAdapter) listAdapter).resume();
261 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700262 invalidateHeaders();
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900263
264 registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700265 }
266
267 @Override
268 public void onPause() {
269 super.onPause();
270
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900271 unregisterReceiver(mBatteryInfoReceiver);
272
Gilles Debunnee78c1872011-06-20 15:00:07 -0700273 ListAdapter listAdapter = getListAdapter();
274 if (listAdapter instanceof HeaderAdapter) {
275 ((HeaderAdapter) listAdapter).pause();
Amith Yamasani86708a82012-06-06 20:23:08 -0700276 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700277
278 mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
279 mDevelopmentPreferencesListener);
280 mDevelopmentPreferencesListener = null;
Amith Yamasani86708a82012-06-06 20:23:08 -0700281 }
282
283 @Override
284 public void onDestroy() {
285 super.onDestroy();
286 if (mListeningToAccountUpdates) {
Amith Yamasani56821db2012-06-05 13:20:45 -0700287 AccountManager.get(this).removeOnAccountsUpdatedListener(this);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700288 }
289 }
290
Amith Yamasani56f51a82013-08-05 10:07:23 -0700291 @Override
292 public boolean onIsMultiPane() {
293 return false;
294 }
295
Amith Yamasania677ee22013-07-26 13:38:41 -0700296 private static final String[] ENTRY_FRAGMENTS = {
297 WirelessSettings.class.getName(),
298 WifiSettings.class.getName(),
299 AdvancedWifiSettings.class.getName(),
300 BluetoothSettings.class.getName(),
301 TetherSettings.class.getName(),
302 WifiP2pSettings.class.getName(),
303 VpnSettings.class.getName(),
304 DateTimeSettings.class.getName(),
305 LocalePicker.class.getName(),
306 InputMethodAndLanguageSettings.class.getName(),
307 SpellCheckersSettings.class.getName(),
308 UserDictionaryList.class.getName(),
309 UserDictionarySettings.class.getName(),
310 SoundSettings.class.getName(),
311 DisplaySettings.class.getName(),
312 DeviceInfoSettings.class.getName(),
313 ManageApplications.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700314 ProcessStatsUi.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700315 NotificationStation.class.getName(),
316 AppOpsSummary.class.getName(),
317 LocationSettings.class.getName(),
318 SecuritySettings.class.getName(),
319 PrivacySettings.class.getName(),
320 DeviceAdminSettings.class.getName(),
321 AccessibilitySettings.class.getName(),
322 TextToSpeechSettings.class.getName(),
323 Memory.class.getName(),
324 DevelopmentSettings.class.getName(),
325 UsbSettings.class.getName(),
326 AndroidBeam.class.getName(),
327 WifiDisplaySettings.class.getName(),
328 PowerUsageSummary.class.getName(),
329 AccountSyncSettings.class.getName(),
330 CryptKeeperSettings.class.getName(),
331 DataUsageSummary.class.getName(),
332 DreamSettings.class.getName(),
333 UserSettings.class.getName(),
334 NotificationAccessSettings.class.getName(),
Amith Yamasaniee226f92013-08-05 11:02:16 -0700335 ManageAccountsSettings.class.getName(),
Dianne Hackbornc6d658e2013-08-08 12:57:53 -0700336 PrintingSettings.class.getName(),
Amith Yamasania677ee22013-07-26 13:38:41 -0700337 };
338
339 @Override
340 protected boolean isValidFragment(String fragmentName) {
341 // Almost all fragments are wrapped in this,
342 // except for a few that have their own activities.
343 for (int i = 0; i < ENTRY_FRAGMENTS.length; i++) {
344 if (ENTRY_FRAGMENTS[i].equals(fragmentName)) return true;
345 }
346 return false;
347 }
348
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800349 private void switchToHeaderLocal(Header header) {
350 mInLocalHeaderSwitch = true;
351 switchToHeader(header);
352 mInLocalHeaderSwitch = false;
353 }
354
355 @Override
356 public void switchToHeader(Header header) {
357 if (!mInLocalHeaderSwitch) {
358 mCurrentHeader = null;
359 mParentHeader = null;
360 }
361 super.switchToHeader(header);
362 }
363
364 /**
365 * Switch to parent fragment and store the grand parent's info
Jake Hamby2748fc22011-01-12 15:06:28 -0800366 * @param className name of the activity wrapper for the parent fragment.
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800367 */
368 private void switchToParent(String className) {
369 final ComponentName cn = new ComponentName(this, className);
370 try {
371 final PackageManager pm = getPackageManager();
372 final ActivityInfo parentInfo = pm.getActivityInfo(cn, PackageManager.GET_META_DATA);
373
374 if (parentInfo != null && parentInfo.metaData != null) {
375 String fragmentClass = parentInfo.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
376 CharSequence fragmentTitle = parentInfo.loadLabel(pm);
377 Header parentHeader = new Header();
378 parentHeader.fragment = fragmentClass;
379 parentHeader.title = fragmentTitle;
380 mCurrentHeader = parentHeader;
381
382 switchToHeaderLocal(parentHeader);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700383 highlightHeader(mTopLevelHeaderId);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800384
385 mParentHeader = new Header();
386 mParentHeader.fragment
387 = parentInfo.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
388 mParentHeader.title = parentInfo.metaData.getString(META_DATA_KEY_PARENT_TITLE);
389 }
390 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700391 Log.w(LOG_TAG, "Could not find parent activity : " + className);
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800392 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700393 }
394
Amith Yamasani3965ae62010-11-15 14:45:19 -0800395 @Override
396 public void onNewIntent(Intent intent) {
397 super.onNewIntent(intent);
398
399 // If it is not launched from history, then reset to top-level
Amith Yamasanief617232012-10-09 16:57:25 -0700400 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
401 if (mFirstHeader != null && !onIsHidingHeaders() && onIsMultiPane()) {
402 switchToHeaderLocal(mFirstHeader);
403 }
404 getListView().setSelectionFromTop(0, 0);
Amith Yamasani3965ae62010-11-15 14:45:19 -0800405 }
406 }
407
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700408 private void highlightHeader(int id) {
409 if (id != 0) {
410 Integer index = mHeaderIndexMap.get(id);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700411 if (index != null) {
412 getListView().setItemChecked(index, true);
Amith Yamasanief617232012-10-09 16:57:25 -0700413 if (isMultiPane()) {
414 getListView().smoothScrollToPosition(index);
415 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700416 }
417 }
418 }
419
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700420 @Override
421 public Intent getIntent() {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700422 Intent superIntent = super.getIntent();
423 String startingFragment = getStartingFragmentClass(superIntent);
Gilles Debunne3661b622011-06-27 11:19:16 -0700424 // This is called from super.onCreate, isMultiPane() is not yet reliable
425 // Do not use onIsHidingHeaders either, which relies itself on this method
426 if (startingFragment != null && !onIsMultiPane()) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700427 Intent modIntent = new Intent(superIntent);
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700428 modIntent.putExtra(EXTRA_SHOW_FRAGMENT, startingFragment);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700429 Bundle args = superIntent.getExtras();
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700430 if (args != null) {
431 args = new Bundle(args);
432 } else {
433 args = new Bundle();
434 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700435 args.putParcelable("intent", superIntent);
436 modIntent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, superIntent.getExtras());
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700437 return modIntent;
438 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700439 return superIntent;
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700440 }
441
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700442 /**
Amith Yamasani379d9b02010-09-27 12:03:59 -0700443 * Checks if the component name in the intent is different from the Settings class and
444 * returns the class name to load as a fragment.
445 */
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700446 protected String getStartingFragmentClass(Intent intent) {
447 if (mFragmentClass != null) return mFragmentClass;
448
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700449 String intentClass = intent.getComponent().getClassName();
Amith Yamasani379d9b02010-09-27 12:03:59 -0700450 if (intentClass.equals(getClass().getName())) return null;
451
Dianne Hackbornee293792010-11-01 12:32:33 -0700452 if ("com.android.settings.ManageApplications".equals(intentClass)
453 || "com.android.settings.RunningServices".equals(intentClass)
454 || "com.android.settings.applications.StorageUse".equals(intentClass)) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700455 // Old names of manage apps.
Dianne Hackbornf4eb85b2010-10-29 16:53:04 -0700456 intentClass = com.android.settings.applications.ManageApplications.class.getName();
457 }
458
Amith Yamasani379d9b02010-09-27 12:03:59 -0700459 return intentClass;
460 }
461
462 /**
463 * Override initial header when an activity-alias is causing Settings to be launched
464 * for a specific fragment encoded in the android:name parameter.
465 */
466 @Override
467 public Header onGetInitialHeader() {
468 String fragmentClass = getStartingFragmentClass(super.getIntent());
469 if (fragmentClass != null) {
470 Header header = new Header();
471 header.fragment = fragmentClass;
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800472 header.title = getTitle();
Amith Yamasanie0e4fc22010-10-05 11:49:51 -0700473 header.fragmentArguments = getIntent().getExtras();
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800474 mCurrentHeader = header;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700475 return header;
476 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700477
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700478 return mFirstHeader;
Amith Yamasani379d9b02010-09-27 12:03:59 -0700479 }
480
Dianne Hackbornb7258182011-03-15 16:23:55 -0700481 @Override
Dianne Hackborn48147dc2011-03-18 12:29:41 -0700482 public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
483 int titleRes, int shortTitleRes) {
484 Intent intent = super.onBuildStartFragmentIntent(fragmentName, args,
485 titleRes, shortTitleRes);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700486
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800487 // Some fragments want split ActionBar; these should stay in sync with
488 // uiOptions for fragments also defined as activities in manifest.
489 if (WifiSettings.class.getName().equals(fragmentName) ||
490 WifiP2pSettings.class.getName().equals(fragmentName) ||
Jeff Sharkey0c3634c2013-02-20 12:35:16 -0800491 WifiDisplaySettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800492 BluetoothSettings.class.getName().equals(fragmentName) ||
493 DreamSettings.class.getName().equals(fragmentName) ||
Lifu Tangd5fbbc42013-08-01 17:23:10 -0700494 LocationSettings.class.getName().equals(fragmentName) ||
Jeff Sharkeycc0d26b2012-11-27 16:42:27 -0800495 ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName)) {
496 intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
Jeff Sharkey9fab0da2011-07-09 17:52:31 -0700497 }
498
Dianne Hackbornb7258182011-03-15 16:23:55 -0700499 intent.setClass(this, SubSettings.class);
500 return intent;
501 }
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700502
Amith Yamasani379d9b02010-09-27 12:03:59 -0700503 /**
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700504 * Populate the activity with the top-level headers.
505 */
Amith Yamasanid7993472010-08-18 13:59:28 -0700506 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700507 public void onBuildHeaders(List<Header> headers) {
508 loadHeadersFromResource(R.xml.settings_headers, headers);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700509 updateHeaderList(headers);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700510 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700511
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700512 private void updateHeaderList(List<Header> target) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700513 final boolean showDev = mDevelopmentPreferences.getBoolean(
514 DevelopmentSettings.PREF_SHOW,
515 android.os.Build.TYPE.equals("eng"));
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700516 int i = 0;
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400517
518 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700519 mHeaderIndexMap.clear();
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700520 while (i < target.size()) {
521 Header header = target.get(i);
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700522 // Ids are integers, so downcasting
523 int id = (int) header.id;
Chris Wren2bc32ae2012-09-24 14:23:46 -0400524 if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700525 Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
Gilles Debunne2454f492011-06-21 16:16:06 -0700526 } else if (id == R.id.wifi_settings) {
527 // Remove WiFi Settings if WiFi service is not available.
528 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700529 target.remove(i);
Gilles Debunne2454f492011-06-21 16:16:06 -0700530 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700531 } else if (id == R.id.bluetooth_settings) {
532 // Remove Bluetooth Settings if Bluetooth service is not available.
Gilles Debunne2454f492011-06-21 16:16:06 -0700533 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700534 target.remove(i);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700535 }
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700536 } else if (id == R.id.data_usage_settings) {
537 // Remove data usage when kernel module not enabled
538 final INetworkManagementService netManager = INetworkManagementService.Stub
539 .asInterface(ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
540 try {
541 if (!netManager.isBandwidthControlEnabled()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700542 target.remove(i);
Jeff Sharkey34e964d2012-04-21 15:41:48 -0700543 }
544 } catch (RemoteException e) {
545 // ignored
546 }
Jaewan Kima3fe77b2013-06-04 21:17:40 +0900547 } else if (id == R.id.battery_settings) {
548 // Remove battery settings when battery is not available. (e.g. TV)
549
550 if (!mBatteryPresent) {
551 target.remove(i);
552 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700553 } else if (id == R.id.account_settings) {
554 int headerIndex = i + 1;
555 i = insertAccountsHeaders(target, headerIndex);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700556 } else if (id == R.id.user_settings) {
Amith Yamasanidc6bfa62012-09-06 18:04:06 -0700557 if (!UserHandle.MU_ENABLED
Jeff Sharkey44202462012-09-19 13:13:45 -0700558 || !UserManager.supportsMultipleUsers()
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700559 || Utils.isMonkeyRunning()) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700560 target.remove(i);
561 }
Martijn Coenen26515da2013-08-01 18:13:33 -0700562 } else if (id == R.id.nfc_payment_settings) {
563 if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HCE)) {
564 target.remove(i);
565 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700566 } else if (id == R.id.development_settings) {
567 if (!showDev) {
568 target.remove(i);
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700569 }
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400570 } else if (id == R.id.account_add) {
571 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
572 target.remove(i);
573 }
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700574 }
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700575
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900576 if (i < target.size() && target.get(i) == header
Amith Yamasanib99f8642012-10-10 21:41:12 -0700577 && UserHandle.MU_ENABLED && UserHandle.myUserId() != 0
Amith Yamasanib810a0d2012-03-25 10:12:26 -0700578 && !ArrayUtils.contains(SETTINGS_FOR_RESTRICTED, id)) {
Dianne Hackborncaefa9b2012-10-10 15:05:42 -0700579 target.remove(i);
Amith Yamasanid7993472010-08-18 13:59:28 -0700580 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700581
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700582 // Increment if the current one wasn't removed by the Utils code.
Jaewan Kimbb0e6212013-02-04 15:36:17 +0900583 if (i < target.size() && target.get(i) == header) {
Amith Yamasani3965ae62010-11-15 14:45:19 -0800584 // Hold on to the first header, when we need to reset to the top-level
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700585 if (mFirstHeader == null &&
586 HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
587 mFirstHeader = header;
588 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700589 mHeaderIndexMap.put(id, i);
Amith Yamasani02cf71a2010-09-21 15:48:52 -0700590 i++;
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700591 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700592 }
593 }
594
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700595 private int insertAccountsHeaders(List<Header> target, int headerIndex) {
596 String[] accountTypes = mAuthenticatorHelper.getEnabledAccountTypes();
597 List<Header> accountHeaders = new ArrayList<Header>(accountTypes.length);
598 for (String accountType : accountTypes) {
599 CharSequence label = mAuthenticatorHelper.getLabelForType(this, accountType);
Brian Muramatsuc28af522012-06-28 14:25:14 -0700600 if (label == null) {
601 continue;
602 }
603
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700604 Account[] accounts = AccountManager.get(this).getAccountsByType(accountType);
605 boolean skipToAccount = accounts.length == 1
606 && !mAuthenticatorHelper.hasAccountPreferences(accountType);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700607 Header accHeader = new Header();
608 accHeader.title = label;
609 if (accHeader.extras == null) {
610 accHeader.extras = new Bundle();
611 }
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700612 if (skipToAccount) {
613 accHeader.breadCrumbTitleRes = R.string.account_sync_settings_title;
614 accHeader.breadCrumbShortTitleRes = R.string.account_sync_settings_title;
615 accHeader.fragment = AccountSyncSettings.class.getName();
616 accHeader.fragmentArguments = new Bundle();
617 // Need this for the icon
618 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
619 accHeader.extras.putParcelable(AccountSyncSettings.ACCOUNT_KEY, accounts[0]);
620 accHeader.fragmentArguments.putParcelable(AccountSyncSettings.ACCOUNT_KEY,
621 accounts[0]);
622 } else {
623 accHeader.breadCrumbTitle = label;
624 accHeader.breadCrumbShortTitle = label;
625 accHeader.fragment = ManageAccountsSettings.class.getName();
626 accHeader.fragmentArguments = new Bundle();
627 accHeader.extras.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE, accountType);
628 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_TYPE,
629 accountType);
630 if (!isMultiPane()) {
631 accHeader.fragmentArguments.putString(ManageAccountsSettings.KEY_ACCOUNT_LABEL,
632 label.toString());
633 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700634 }
635 accountHeaders.add(accHeader);
636 }
637
638 // Sort by label
639 Collections.sort(accountHeaders, new Comparator<Header>() {
640 @Override
641 public int compare(Header h1, Header h2) {
642 return h1.title.toString().compareTo(h2.title.toString());
643 }
644 });
645
646 for (Header header : accountHeaders) {
647 target.add(headerIndex++, header);
648 }
Amith Yamasani86708a82012-06-06 20:23:08 -0700649 if (!mListeningToAccountUpdates) {
650 AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);
651 mListeningToAccountUpdates = true;
652 }
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700653 return headerIndex;
654 }
655
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700656 private void getMetaData() {
657 try {
658 ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
659 PackageManager.GET_META_DATA);
660 if (ai == null || ai.metaData == null) return;
661 mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
662 mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700663
Amith Yamasanic9fdfa82010-12-14 14:38:16 -0800664 // Check if it has a parent specified and create a Header object
665 final int parentHeaderTitleRes = ai.metaData.getInt(META_DATA_KEY_PARENT_TITLE);
666 String parentFragmentClass = ai.metaData.getString(META_DATA_KEY_PARENT_FRAGMENT_CLASS);
667 if (parentFragmentClass != null) {
668 mParentHeader = new Header();
669 mParentHeader.fragment = parentFragmentClass;
670 if (parentHeaderTitleRes != 0) {
671 mParentHeader.title = getResources().getString(parentHeaderTitleRes);
672 }
673 }
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700674 } catch (NameNotFoundException nnfe) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700675 // No recovery
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700676 }
677 }
678
Amith Yamasani9e3a4702011-01-11 09:09:26 -0800679 @Override
680 public boolean hasNextButton() {
681 return super.hasNextButton();
682 }
683
684 @Override
685 public Button getNextButton() {
686 return super.getNextButton();
687 }
688
Gilles Debunnee78c1872011-06-20 15:00:07 -0700689 private static class HeaderAdapter extends ArrayAdapter<Header> {
690 static final int HEADER_TYPE_CATEGORY = 0;
691 static final int HEADER_TYPE_NORMAL = 1;
692 static final int HEADER_TYPE_SWITCH = 2;
693 private static final int HEADER_TYPE_COUNT = HEADER_TYPE_SWITCH + 1;
694
695 private final WifiEnabler mWifiEnabler;
696 private final BluetoothEnabler mBluetoothEnabler;
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700697 private AuthenticatorHelper mAuthHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700698
699 private static class HeaderViewHolder {
700 ImageView icon;
701 TextView title;
702 TextView summary;
703 Switch switch_;
704 }
705
706 private LayoutInflater mInflater;
707
708 static int getHeaderType(Header header) {
709 if (header.fragment == null && header.intent == null) {
710 return HEADER_TYPE_CATEGORY;
711 } else if (header.id == R.id.wifi_settings || header.id == R.id.bluetooth_settings) {
712 return HEADER_TYPE_SWITCH;
713 } else {
714 return HEADER_TYPE_NORMAL;
715 }
716 }
717
718 @Override
719 public int getItemViewType(int position) {
720 Header header = getItem(position);
721 return getHeaderType(header);
722 }
723
724 @Override
725 public boolean areAllItemsEnabled() {
726 return false; // because of categories
727 }
728
729 @Override
730 public boolean isEnabled(int position) {
731 return getItemViewType(position) != HEADER_TYPE_CATEGORY;
732 }
733
734 @Override
735 public int getViewTypeCount() {
736 return HEADER_TYPE_COUNT;
737 }
738
739 @Override
740 public boolean hasStableIds() {
741 return true;
742 }
743
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700744 public HeaderAdapter(Context context, List<Header> objects,
745 AuthenticatorHelper authenticatorHelper) {
Gilles Debunnee78c1872011-06-20 15:00:07 -0700746 super(context, 0, objects);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700747
748 mAuthHelper = authenticatorHelper;
Gilles Debunnee78c1872011-06-20 15:00:07 -0700749 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700750
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700751 // Temp Switches provided as placeholder until the adapter replaces these with actual
Gilles Debunnee78c1872011-06-20 15:00:07 -0700752 // Switches inflated from their layouts. Must be done before adapter is set in super
753 mWifiEnabler = new WifiEnabler(context, new Switch(context));
754 mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
755 }
756
757 @Override
758 public View getView(int position, View convertView, ViewGroup parent) {
759 HeaderViewHolder holder;
760 Header header = getItem(position);
761 int headerType = getHeaderType(header);
762 View view = null;
763
764 if (convertView == null) {
765 holder = new HeaderViewHolder();
766 switch (headerType) {
767 case HEADER_TYPE_CATEGORY:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700768 view = new TextView(getContext(), null,
769 android.R.attr.listSeparatorTextViewStyle);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700770 holder.title = (TextView) view;
771 break;
772
773 case HEADER_TYPE_SWITCH:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700774 view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
775 false);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700776 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700777 holder.title = (TextView)
778 view.findViewById(com.android.internal.R.id.title);
779 holder.summary = (TextView)
780 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700781 holder.switch_ = (Switch) view.findViewById(R.id.switchWidget);
782 break;
783
784 case HEADER_TYPE_NORMAL:
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700785 view = mInflater.inflate(
Amith Yamasanic8a93172012-06-08 13:35:47 -0700786 R.layout.preference_header_item, parent,
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700787 false);
Amith Yamasanic8a93172012-06-08 13:35:47 -0700788 holder.icon = (ImageView) view.findViewById(R.id.icon);
Gilles Debunneb396c9b2011-06-22 16:07:29 -0700789 holder.title = (TextView)
790 view.findViewById(com.android.internal.R.id.title);
791 holder.summary = (TextView)
792 view.findViewById(com.android.internal.R.id.summary);
Gilles Debunnee78c1872011-06-20 15:00:07 -0700793 break;
794 }
795 view.setTag(holder);
796 } else {
797 view = convertView;
798 holder = (HeaderViewHolder) view.getTag();
799 }
800
801 // All view fields must be updated every time, because the view may be recycled
802 switch (headerType) {
803 case HEADER_TYPE_CATEGORY:
804 holder.title.setText(header.getTitle(getContext().getResources()));
805 break;
806
807 case HEADER_TYPE_SWITCH:
808 // Would need a different treatment if the main menu had more switches
809 if (header.id == R.id.wifi_settings) {
810 mWifiEnabler.setSwitch(holder.switch_);
811 } else {
812 mBluetoothEnabler.setSwitch(holder.switch_);
813 }
814 // No break, fall through on purpose to update common fields
815
816 //$FALL-THROUGH$
817 case HEADER_TYPE_NORMAL:
Amith Yamasani3882c2e2012-06-07 17:03:20 -0700818 if (header.extras != null
819 && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700820 String accType = header.extras.getString(
821 ManageAccountsSettings.KEY_ACCOUNT_TYPE);
822 ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
823 lp.width = getContext().getResources().getDimensionPixelSize(
824 R.dimen.header_icon_width);
825 lp.height = lp.width;
826 holder.icon.setLayoutParams(lp);
827 Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
828 holder.icon.setImageDrawable(icon);
829 } else {
830 holder.icon.setImageResource(header.iconRes);
831 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700832 holder.title.setText(header.getTitle(getContext().getResources()));
833 CharSequence summary = header.getSummary(getContext().getResources());
834 if (!TextUtils.isEmpty(summary)) {
835 holder.summary.setVisibility(View.VISIBLE);
836 holder.summary.setText(summary);
837 } else {
838 holder.summary.setVisibility(View.GONE);
839 }
840 break;
841 }
842
843 return view;
844 }
845
846 public void resume() {
847 mWifiEnabler.resume();
848 mBluetoothEnabler.resume();
849 }
Brian Muramatsuc28af522012-06-28 14:25:14 -0700850
Gilles Debunnee78c1872011-06-20 15:00:07 -0700851 public void pause() {
852 mWifiEnabler.pause();
853 mBluetoothEnabler.pause();
854 }
855 }
856
857 @Override
Amith Yamasanid1ab8282012-05-18 09:50:08 -0700858 public void onHeaderClick(Header header, int position) {
859 boolean revert = false;
860 if (header.id == R.id.account_add) {
861 revert = true;
862 }
863
864 super.onHeaderClick(header, position);
865
866 if (revert && mLastHeader != null) {
867 highlightHeader((int) mLastHeader.id);
868 } else {
869 mLastHeader = header;
870 }
871 }
872
873 @Override
Amith Yamasania4379d62011-07-22 10:34:58 -0700874 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
875 // Override the fragment title for Wallpaper settings
Amith Yamasanidfb65432011-11-29 16:38:14 -0800876 int titleRes = pref.getTitleRes();
Amith Yamasania4379d62011-07-22 10:34:58 -0700877 if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
Amith Yamasanidfb65432011-11-29 16:38:14 -0800878 titleRes = R.string.wallpaper_settings_fragment_title;
Amith Yamasani8666b9e2012-09-27 14:50:13 -0700879 } else if (pref.getFragment().equals(OwnerInfoSettings.class.getName())
880 && UserHandle.myUserId() != UserHandle.USER_OWNER) {
Amith Yamasanib0171712013-04-28 22:13:22 -0700881 if (UserManager.get(this).isLinkedUser()) {
882 titleRes = R.string.profile_info_settings_title;
883 } else {
884 titleRes = R.string.user_info_settings_title;
885 }
Amith Yamasania4379d62011-07-22 10:34:58 -0700886 }
Jean Chalard7dabe452012-05-10 18:08:07 +0900887 startPreferencePanel(pref.getFragment(), pref.getExtras(), titleRes, pref.getTitle(),
888 null, 0);
Amith Yamasania4379d62011-07-22 10:34:58 -0700889 return true;
890 }
891
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400892 @Override
Amith Yamasani3d384f42012-05-11 15:22:04 -0700893 public boolean shouldUpRecreateTask(Intent targetIntent) {
894 return super.shouldUpRecreateTask(new Intent(this, Settings.class));
895 }
896
Amith Yamasania4379d62011-07-22 10:34:58 -0700897 @Override
Gilles Debunnee78c1872011-06-20 15:00:07 -0700898 public void setListAdapter(ListAdapter adapter) {
Amith Yamasaniea7b28c2012-06-20 13:51:40 -0700899 if (adapter == null) {
900 super.setListAdapter(null);
901 } else {
902 super.setListAdapter(new HeaderAdapter(this, getHeaders(), mAuthenticatorHelper));
Gilles Debunnee78c1872011-06-20 15:00:07 -0700903 }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700904 }
905
Amith Yamasani56821db2012-06-05 13:20:45 -0700906 @Override
907 public void onAccountsUpdated(Account[] accounts) {
Jeff Sharkey9ff79c12012-10-03 16:48:17 -0700908 // TODO: watch for package upgrades to invalidate cache; see 7206643
909 mAuthenticatorHelper.updateAuthDescriptions(this);
Amith Yamasani56821db2012-06-05 13:20:45 -0700910 mAuthenticatorHelper.onAccountsUpdated(this, accounts);
911 invalidateHeaders();
912 }
913
Amith Yamasani5203bdf2010-11-04 09:59:44 -0700914 /*
915 * Settings subclasses for launching independently.
916 */
Gilles Debunnee78c1872011-06-20 15:00:07 -0700917 public static class BluetoothSettingsActivity extends Settings { /* empty */ }
918 public static class WirelessSettingsActivity extends Settings { /* empty */ }
919 public static class TetherSettingsActivity extends Settings { /* empty */ }
920 public static class VpnSettingsActivity extends Settings { /* empty */ }
921 public static class DateTimeSettingsActivity extends Settings { /* empty */ }
922 public static class StorageSettingsActivity extends Settings { /* empty */ }
923 public static class WifiSettingsActivity extends Settings { /* empty */ }
repo syncb98463f2011-06-30 10:58:43 -0700924 public static class WifiP2pSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700925 public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
Jeff Browne46c5f32012-04-05 11:42:18 -0700926 public static class KeyboardLayoutPickerActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700927 public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
satoke077d2b2011-07-25 09:38:11 +0900928 public static class SpellCheckersSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700929 public static class LocalePickerActivity extends Settings { /* empty */ }
930 public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
931 public static class SoundSettingsActivity extends Settings { /* empty */ }
932 public static class DisplaySettingsActivity extends Settings { /* empty */ }
933 public static class DeviceInfoSettingsActivity extends Settings { /* empty */ }
934 public static class ApplicationSettingsActivity extends Settings { /* empty */ }
935 public static class ManageApplicationsActivity extends Settings { /* empty */ }
Dianne Hackborna522a8e2013-01-15 19:02:05 -0800936 public static class AppOpsSummaryActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700937 public static class StorageUseActivity extends Settings { /* empty */ }
938 public static class DevelopmentSettingsActivity extends Settings { /* empty */ }
939 public static class AccessibilitySettingsActivity extends Settings { /* empty */ }
940 public static class SecuritySettingsActivity extends Settings { /* empty */ }
Gilles Debunnea6a8a142011-06-09 11:56:17 -0700941 public static class LocationSettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700942 public static class PrivacySettingsActivity extends Settings { /* empty */ }
Gilles Debunnee78c1872011-06-20 15:00:07 -0700943 public static class RunningServicesActivity extends Settings { /* empty */ }
944 public static class ManageAccountsSettingsActivity extends Settings { /* empty */ }
945 public static class PowerUsageSummaryActivity extends Settings { /* empty */ }
946 public static class AccountSyncSettingsActivity extends Settings { /* empty */ }
947 public static class AccountSyncSettingsInAddAccountActivity extends Settings { /* empty */ }
948 public static class CryptKeeperSettingsActivity extends Settings { /* empty */ }
949 public static class DeviceAdminSettingsActivity extends Settings { /* empty */ }
950 public static class DataUsageSummaryActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700951 public static class AdvancedWifiSettingsActivity extends Settings { /* empty */ }
Gilles Debunneab189bd2011-07-06 13:10:16 -0700952 public static class TextToSpeechSettingsActivity extends Settings { /* empty */ }
Jeff Hamilton3d670de2011-09-21 16:44:36 -0500953 public static class AndroidBeamSettingsActivity extends Settings { /* empty */ }
Jeff Brown9e143f52012-09-19 20:46:07 -0700954 public static class WifiDisplaySettingsActivity extends Settings { /* empty */ }
Daniel Sandler7dee75c2012-11-27 22:41:30 -0500955 public static class DreamSettingsActivity extends Settings { /* empty */ }
Daniel Sandler328e2d22013-01-17 13:14:02 -0500956 public static class NotificationStationActivity extends Settings { /* empty */ }
Amith Yamasani233592b2013-03-01 17:05:23 -0800957 public static class UserSettingsActivity extends Settings { /* empty */ }
Daniel Sandler79b9bfe2013-04-04 14:30:04 -0400958 public static class NotificationAccessSettingsActivity extends Settings { /* empty */ }
Amith Yamasania677ee22013-07-26 13:38:41 -0700959 public static class UsbSettingsActivity extends Settings { /* empty */ }
Martijn Coenen26515da2013-08-01 18:13:33 -0700960 public static class NfcPaymentActivity extends Settings { /* empty */ }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800961}