From 39f40c7687c9eeba56e60250366b4bd383e53a26 Mon Sep 17 00:00:00 2001 From: Brian Carlstrom Date: Thu, 30 Jan 2014 13:14:02 -0800 Subject: [PATCH 01/18] packages/apps/Settings: Rename persist.sys.dalvik.vm.lib to allow new default Bug: 12798969 Change-Id: I1937c2ff758214e1c9d369e475ae4efbba4f9dec --- src/com/android/settings/DevelopmentSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java index f16a19bf861..f8b4fd3c168 100644 --- a/src/com/android/settings/DevelopmentSettings.java +++ b/src/com/android/settings/DevelopmentSettings.java @@ -95,7 +95,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment private static final String KEEP_SCREEN_ON = "keep_screen_on"; private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log"; private static final String SELECT_RUNTIME_KEY = "select_runtime"; - private static final String SELECT_RUNTIME_PROPERTY = "persist.sys.dalvik.vm.lib"; + private static final String SELECT_RUNTIME_PROPERTY = "persist.sys.dalvik.vm.lib.1"; private static final String ALLOW_MOCK_LOCATION = "allow_mock_location"; private static final String HDCP_CHECKING_KEY = "hdcp_checking"; private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking"; From 6a2d0ca9f4a30b62f7551e70695dd648305c0778 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Tue, 4 Feb 2014 12:41:30 -0800 Subject: [PATCH 02/18] Fix bug #12890490 Crash in Settings observed after tap on Preferred Engine settings and Cloud print option - when setting the Fragment's title use the CharSequence when the titleRes ID is "0" Change-Id: I54e5379172632acfc967b5ea401ba90f73b41748 --- .../android/settings/SettingsActivity.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index c3d067f7301..a362ee622f6 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -924,7 +924,7 @@ public class SettingsActivity extends Activity public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes, CharSequence titleText, Fragment resultTo, int resultRequestCode) { - startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, 0); + startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText); } /** @@ -965,16 +965,16 @@ public class SettingsActivity extends Activity * @param fragmentName The name of the fragment to display. * @param args Optional arguments to supply to the fragment. * @param resultTo Option fragment that should receive the result of - * the activity launch. - * @param resultRequestCode If resultTo is non-null, this is the request - * code in which to report the result. - * @param titleRes Resource ID of string to display for the title of - * this set of preferences. - * @param shortTitleRes Resource ID of string to display for the short title of - * this set of preferences. + * the activity launch. + * @param resultRequestCode If resultTo is non-null, this is the request code in which to + * report the result. + * @param titleRes Resource ID of string to display for the title of. If the Resource ID is a + * valid one then it will be used to get the title. Otherwise the titleText + * argument will be used as the title. + * @param titleText string to display for the title of. */ private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo, - int resultRequestCode, int titleRes, int shortTitleRes) { + int resultRequestCode, int titleRes, CharSequence titleText) { Fragment f = Fragment.instantiate(this, fragmentName, args); if (resultTo != null) { f.setTargetFragment(resultTo, resultRequestCode); @@ -985,10 +985,17 @@ public class SettingsActivity extends Activity transaction.addToBackStack(BACK_STACK_PREFS); transaction.commitAllowingStateLoss(); - final CharSequence title = getText(titleRes); - final TitlePair pair = new TitlePair(titleRes, null); + final TitlePair pair; + final CharSequence cs; + if (titleRes != 0) { + pair = new TitlePair(titleRes, null); + cs = getText(titleRes); + } else { + pair = new TitlePair(0, titleText); + cs = titleText; + } + setTitle(cs); mTitleStack.add(pair); - setTitle(title); } /** @@ -1583,7 +1590,7 @@ public class SettingsActivity extends Activity /** * Called when the user selects an item in the header list. The default * implementation will call either - * {@link #startWithFragment(String, Bundle, Fragment, int, int, int)} + * {@link #startWithFragment(String, android.os.Bundle, android.app.Fragment, int, int, CharSequence)} * or {@link #switchToHeader(com.android.settings.SettingsActivity.Header, boolean)} * as appropriate. * From 3513cda38c613a22192a6f6a5800b18fe4df13c3 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Tue, 4 Feb 2014 14:01:39 -0800 Subject: [PATCH 03/18] Fix bug #12890909 Tablets: Settings crashes when tapped on Add Account option in settings - remove android:theme="@android:style/Theme.Holo.DialogWhenLarge" for com.android.settings.Settings$ChooseAccountActivity Change-Id: Ife94e93e057029a71fe4a276f7ef9b98c9561b87 --- AndroidManifest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ec01534e3d8..6ba9a94fb46 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1538,8 +1538,7 @@ + android:configChanges="orientation|keyboardHidden|screenSize"> From b608b8a4344fcf5b6de40b87c61a9ca0e6e2bf0f Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Tue, 4 Feb 2014 14:20:28 -0800 Subject: [PATCH 04/18] Fix bug #12895706 BT settings crash with java.lang.ClassCastException: com.android.settings.Settings cannot be cast to android.preference.PreferenceActivity - remove the PreferenceActivity related code as we are no more using PreferenceActivity (and Settings is a derive of SettingsActivity) Change-Id: I3c650c03cd205d9c06679974ae4d832ced25459b --- .../settings/bluetooth/LocalDeviceProfilesSettings.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java b/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java index f01bbf5eca9..8d7100745fc 100644 --- a/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java +++ b/src/com/android/settings/bluetooth/LocalDeviceProfilesSettings.java @@ -19,7 +19,6 @@ package com.android.settings.bluetooth; import android.os.Bundle; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; -import android.preference.PreferenceActivity; import android.preference.PreferenceScreen; import com.android.settings.R; @@ -73,8 +72,6 @@ public final class LocalDeviceProfilesSettings extends SettingsPreferenceFragmen // preference can be updated when the timeout changes. mDiscoverableEnabler.setVisibilityPreference(mVisibilityPref); - PreferenceActivity mActivity = (PreferenceActivity)getActivity(); - mActivity.showBreadCrumbs(mManager.getBluetoothAdapter().getName(), ""); PreferenceScreen bluetoothBroadcast = (PreferenceScreen)findPreference(KEY_BROADCASTING); mAdvertisingEnabler = new BluetoothAdvertisingEnabler(getActivity(), bluetoothBroadcast); mManager.setBluetoothAdvertisingEnabler(mAdvertisingEnabler); From 49d98bb566100ef480d4e1228f87319f5bfd5ff3 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Wed, 5 Feb 2014 12:53:04 -0800 Subject: [PATCH 05/18] Fix bug #12903673 Stability: 47 ANRs in com.android.settings - fix the recursive call (probably introduced by some search/replace) Change-Id: I563a68c2cc141a59ef8bb9dd64cd67a62dbfcd4a --- src/com/android/settings/accounts/SyncSettingsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/accounts/SyncSettingsActivity.java b/src/com/android/settings/accounts/SyncSettingsActivity.java index bbd9f919081..9b1bc32e760 100644 --- a/src/com/android/settings/accounts/SyncSettingsActivity.java +++ b/src/com/android/settings/accounts/SyncSettingsActivity.java @@ -27,7 +27,7 @@ import com.android.settings.SettingsActivity; public class SyncSettingsActivity extends SettingsActivity { @Override public Intent getIntent() { - Intent modIntent = new Intent(getIntent()); + Intent modIntent = new Intent(super.getIntent()); modIntent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, SyncSettings.class.getName()); modIntent.putExtra(SettingsActivity.EXTRA_NO_HEADERS, true); return modIntent; From 6f77c70877bd13e32baecec03b7a469f491a3a6d Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Wed, 5 Feb 2014 15:13:46 -0800 Subject: [PATCH 06/18] Fix bug #12898564 Settings Crash on Renaming the device. - remove the call to PreferencesActivity as we are no more using the PreferencesActivity Also set correct activity title with the new selected BT name for the device. Change-Id: I03497187e0410ff2bba87bdb04a197938d1ea967 --- .../settings/bluetooth/BluetoothNameDialogFragment.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java index 0af9c4ed7c4..bf0356c3147 100644 --- a/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothNameDialogFragment.java @@ -26,7 +26,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; -import android.preference.PreferenceActivity; import android.text.Editable; import android.text.InputFilter; import android.text.TextWatcher; @@ -179,9 +178,8 @@ public final class BluetoothNameDialogFragment extends DialogFragment implements mDeviceNameUpdated = true; mDeviceNameEdited = false; mDeviceNameView.setText(mLocalAdapter.getName()); + getActivity().setTitle(mLocalAdapter.getName()); } - PreferenceActivity activity = (PreferenceActivity)getActivity(); - activity.showBreadCrumbs(mLocalAdapter.getName(), ""); } public void afterTextChanged(Editable s) { From c4776b90fc14f1f36596dac99a95b63b40d87695 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Thu, 6 Feb 2014 11:20:24 -0800 Subject: [PATCH 07/18] Fix bug #12890909 Settings crashes when tapped on Add Account option in settings Follow up from the previous CL that was trying to fix it. - remove the dialog theme android:theme="@android:style/Theme.Holo.Dialog" as a Dialog does not support a Drawwer Change-Id: I8b3fe89c157f0b454464c04a4acd4f32049bde71 --- AndroidManifest.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6ba9a94fb46..6e01aecb824 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1514,8 +1514,7 @@ + android:label="@string/account_sync_settings_title"> From 011c262e0da9f6882db35a2e9f1f2e9ea7cfc65a Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Thu, 6 Feb 2014 15:46:19 -0800 Subject: [PATCH 08/18] Fix bug #12910775 Settings crash after tap on Access Point Names under Mobile networks - ApnSettings is now a fragment so introduce a new ApnSettingsActivity - ApsSettingsActivity will use the ApnSettings fragment - move the getListView() call to onActivityCreated(...) as the ListView needs to be created before this call can be done. - add also an alias for the old activity name ".ApsSettings" Change-Id: Id228722d7f34415d4b036282f0845e28546111df --- AndroidManifest.xml | 15 ++++++++++++++- src/com/android/settings/ApnSettings.java | 8 +++++++- src/com/android/settings/Settings.java | 1 + src/com/android/settings/SettingsActivity.java | 3 ++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 6e01aecb824..cc407dbddab 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -259,7 +259,7 @@ - + + + + + + Date: Tue, 11 Feb 2014 19:50:56 +0000 Subject: [PATCH 09/18] There are several painful issues with the initial CL. Doing a revert for now and will rework this. Revert "Fix bug #12939786 BACK should go back into the Fragments BackStack and finally to Overview ...and then exit the Settings App" This reverts commit 4cc95a53c2d9080095c4e1e06f815b8bc7a2cdfe. Change-Id: Iaa21d4771d0b004eff3d8e68b91b546a633d8f23 --- .../android/settings/ChooseLockGeneric.java | 3 +- .../android/settings/SettingsActivity.java | 266 ++++++++++-------- .../print/PrintServiceSettingsFragment.java | 8 + 3 files changed, 152 insertions(+), 125 deletions(-) diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java index 6eaf08b90e2..a92f5144bcb 100644 --- a/src/com/android/settings/ChooseLockGeneric.java +++ b/src/com/android/settings/ChooseLockGeneric.java @@ -27,7 +27,6 @@ import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.preference.Preference; -import android.preference.PreferenceActivity; import android.preference.PreferenceScreen; import android.security.KeyStore; import android.util.EventLog; @@ -42,7 +41,7 @@ import java.util.List; import libcore.util.MutableBoolean; -public class ChooseLockGeneric extends PreferenceActivity { +public class ChooseLockGeneric extends SettingsActivity { @Override public Intent getIntent() { diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 8bfde063c9a..af0d8bb157b 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -70,6 +70,7 @@ import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; @@ -399,7 +400,7 @@ public class SettingsActivity extends Activity @Override public void onItemClick(AdapterView parent, View view, int position, long id) { mDrawerLayout.closeDrawer(mDrawer); - onListItemClick((ListView) parent, view, position, id); + onListItemClick((ListView)parent, view, position, id); } } @@ -516,6 +517,7 @@ public class SettingsActivity extends Activity mDrawer = (ListView) findViewById(R.id.headers_drawer); mDrawer.setAdapter(mHeaderAdapter); mDrawer.setOnItemClickListener(new DrawerItemClickListener()); + mDrawer.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close); @@ -538,23 +540,31 @@ public class SettingsActivity extends Activity } } else { - // We need to first to build the headers. - onBuildHeaders(mHeaders); - - final CharSequence initialTitle = getTitle(); - - // If there are headers, get the initial fragment and push it first so that pressing - // BACK will always go to it before exiting the app - if (mHeaders.size() > 0) { - switchToHeader(mFirstHeader, false, true); - } - - // Got to the initial fragment if one is specified if (initialFragment != null) { - final int initialTitleRes = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); - final Header h = - onGetInitialHeader(initialTitle, initialTitleRes, initialArguments); - switchToHeader(h, false, false); + // If we are just showing a fragment, we want to run in + // new fragment mode, but don't need to compute and show + // the headers. + switchToHeader(initialFragment, initialArguments, true); + + final int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); + if (initialTitle != 0) { + setTitle(getText(initialTitle)); + } + } else { + // We need to try to build the headers. + onBuildHeaders(mHeaders); + + // If there are headers, then at this point we need to show + // them and, depending on the screen, we may also show in-line + // the currently selected preference fragment. + if (mHeaders.size() > 0) { + if (initialFragment == null) { + Header h = onGetInitialHeader(); + switchToHeader(h, false); + } else { + switchToHeader(initialFragment, initialArguments, false); + } + } } } @@ -625,7 +635,7 @@ public class SettingsActivity extends Activity @Override public void onBackStackChanged() { - final int count = getFragmentManager().getBackStackEntryCount(); + final int count = getFragmentManager().getBackStackEntryCount() + 1; TitlePair pair = null; int last; while (mTitleStack.size() > count) { @@ -647,9 +657,6 @@ public class SettingsActivity extends Activity } setTitle(title); } - } else { - final String title = getResources().getString(R.string.settings_label); - setTitle(title); } } } @@ -739,18 +746,20 @@ public class SettingsActivity extends Activity * preference fragment. * * @param header The new header to display. - * @param validate true means that the fragment's Header needs to be validated. - * @param initial true means that the fragment is the initial one. + * @param validate true means that the fragment's Header needs to be validated */ - private void switchToHeader(Header header, boolean validate, boolean initial) { - if (mCurHeader != header) { + private void switchToHeader(Header header, boolean validate) { + if (mCurHeader == header) { + // This is the header we are currently displaying. Just make sure + // to pop the stack up to its root state. + getFragmentManager().popBackStack(BACK_STACK_PREFS, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + } else { + mTitleStack.clear(); if (header.fragment == null) { throw new IllegalStateException("can't switch to header that has no fragment"); } - getFragmentManager().popBackStackImmediate(BACK_STACK_PREFS, - FragmentManager.POP_BACK_STACK_INCLUSIVE); - mTitleStack.clear(); - switchToHeaderInner(header.fragment, header.fragmentArguments, validate, !initial); + switchToHeaderInner(header.fragment, header.fragmentArguments, validate); setSelectedHeader(header); final CharSequence title; if (header.fragment.equals("com.android.settings.dashboard.DashboardSummary")) { @@ -776,116 +785,44 @@ public class SettingsActivity extends Activity } } - public Header onGetInitialHeader(CharSequence title, int titleRes, Bundle args) { + public Header onGetInitialHeader() { String fragmentClass = getStartingFragmentClass(super.getIntent()); if (fragmentClass != null) { Header header = new Header(); header.fragment = fragmentClass; - header.title = title; - header.titleRes = titleRes; - header.fragmentArguments = args; + header.title = getTitle(); + header.fragmentArguments = getIntent().getExtras(); mCurrentHeader = header; return header; } + return mFirstHeader; } - private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate, - boolean addToBackStack) { + /** + * When in two-pane mode, switch the fragment pane to show the given + * preference fragment. + * + * @param fragmentName The name of the fragment to display. + * @param args Optional arguments to supply to the fragment. + * @param validate true means that the fragment's Header needs to be validated + */ + private void switchToHeader(String fragmentName, Bundle args, boolean validate) { + setSelectedHeader(null); + switchToHeaderInner(fragmentName, args, validate); + } + + private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate) { + getFragmentManager().popBackStack(BACK_STACK_PREFS, + FragmentManager.POP_BACK_STACK_INCLUSIVE); if (validate && !isValidFragment(fragmentName)) { throw new IllegalArgumentException("Invalid fragment for this activity: " + fragmentName); } Fragment f = Fragment.instantiate(this, fragmentName, args); FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.replace(R.id.prefs, f); transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); - if (addToBackStack) { - transaction.addToBackStack(BACK_STACK_PREFS); - } - transaction.commitAllowingStateLoss(); - } - - /** - * Start a new fragment. - * - * @param fragmentName The name of the fragment to display. - * @param args Optional arguments to supply to the fragment. - * @param resultTo Option fragment that should receive the result of - * the activity launch. - * @param resultRequestCode If resultTo is non-null, this is the request code in which to - * report the result. - * @param titleRes Resource ID of string to display for the title of. If the Resource ID is a - * valid one then it will be used to get the title. Otherwise the titleText - * argument will be used as the title. - * @param titleText string to display for the title of. - */ - private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo, - int resultRequestCode, int titleRes, CharSequence titleText) { - Fragment f = Fragment.instantiate(this, fragmentName, args); - if (resultTo != null) { - f.setTargetFragment(resultTo, resultRequestCode); - } - FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.prefs, f); - transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); - transaction.addToBackStack(BACK_STACK_PREFS); - transaction.commitAllowingStateLoss(); - - final TitlePair pair; - final CharSequence cs; - if (titleRes != 0) { - pair = new TitlePair(titleRes, null); - cs = getText(titleRes); - } else { - pair = new TitlePair(0, titleText); - cs = titleText; - } - setTitle(cs); - mTitleStack.add(pair); - } - - /** - * Start a new fragment containing a preference panel. If the preferences - * are being displayed in multi-pane mode, the given fragment class will - * be instantiated and placed in the appropriate pane. If running in - * single-pane mode, a new activity will be launched in which to show the - * fragment. - * - * @param fragmentClass Full name of the class implementing the fragment. - * @param args Any desired arguments to supply to the fragment. - * @param titleRes Optional resource identifier of the title of this - * fragment. - * @param titleText Optional text of the title of this fragment. - * @param resultTo Optional fragment that result data should be sent to. - * If non-null, resultTo.onActivityResult() will be called when this - * preference panel is done. The launched panel must use - * {@link #finishPreferencePanel(Fragment, int, Intent)} when done. - * @param resultRequestCode If resultTo is non-null, this is the caller's - * request code to be received with the resut. - */ - public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes, - CharSequence titleText, Fragment resultTo, - int resultRequestCode) { - startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText); - } - - /** - * Start a new fragment. - * - * @param fragment The fragment to start - * @param push If true, the current fragment will be pushed onto the back stack. If false, - * the current fragment will be replaced. - */ - public void startPreferenceFragment(Fragment fragment, boolean push) { - FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.replace(R.id.prefs, fragment); - if (push) { - transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); - transaction.addToBackStack(BACK_STACK_PREFS); - } else { - transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); - } transaction.commitAllowingStateLoss(); } @@ -966,6 +903,31 @@ public class SettingsActivity extends Activity return intentClass; } + /** + * Start a new fragment containing a preference panel. If the preferences + * are being displayed in multi-pane mode, the given fragment class will + * be instantiated and placed in the appropriate pane. If running in + * single-pane mode, a new activity will be launched in which to show the + * fragment. + * + * @param fragmentClass Full name of the class implementing the fragment. + * @param args Any desired arguments to supply to the fragment. + * @param titleRes Optional resource identifier of the title of this + * fragment. + * @param titleText Optional text of the title of this fragment. + * @param resultTo Optional fragment that result data should be sent to. + * If non-null, resultTo.onActivityResult() will be called when this + * preference panel is done. The launched panel must use + * {@link #finishPreferencePanel(Fragment, int, Intent)} when done. + * @param resultRequestCode If resultTo is non-null, this is the caller's + * request code to be received with the resut. + */ + public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes, + CharSequence titleText, Fragment resultTo, + int resultRequestCode) { + startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText); + } + /** * Called by a preference panel fragment to finish itself. * @@ -979,6 +941,64 @@ public class SettingsActivity extends Activity setResult(resultCode, resultData); } + /** + * Start a new fragment. + * + * @param fragment The fragment to start + * @param push If true, the current fragment will be pushed onto the back stack. If false, + * the current fragment will be replaced. + */ + public void startPreferenceFragment(Fragment fragment, boolean push) { + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.replace(R.id.prefs, fragment); + if (push) { + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); + transaction.addToBackStack(BACK_STACK_PREFS); + } else { + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); + } + transaction.commitAllowingStateLoss(); + } + + /** + * Start a new fragment. + * + * @param fragmentName The name of the fragment to display. + * @param args Optional arguments to supply to the fragment. + * @param resultTo Option fragment that should receive the result of + * the activity launch. + * @param resultRequestCode If resultTo is non-null, this is the request code in which to + * report the result. + * @param titleRes Resource ID of string to display for the title of. If the Resource ID is a + * valid one then it will be used to get the title. Otherwise the titleText + * argument will be used as the title. + * @param titleText string to display for the title of. + */ + private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo, + int resultRequestCode, int titleRes, CharSequence titleText) { + Fragment f = Fragment.instantiate(this, fragmentName, args); + if (resultTo != null) { + f.setTargetFragment(resultTo, resultRequestCode); + } + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + transaction.replace(R.id.prefs, f); + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); + transaction.addToBackStack(BACK_STACK_PREFS); + transaction.commitAllowingStateLoss(); + + final TitlePair pair; + final CharSequence cs; + if (titleRes != 0) { + pair = new TitlePair(titleRes, null); + cs = getText(titleRes); + } else { + pair = new TitlePair(0, titleText); + cs = titleText; + } + setTitle(cs); + mTitleStack.add(pair); + } + /** * Called when the activity needs its list of headers build. By * implementing this and adding at least one item to the list, you @@ -1572,7 +1592,7 @@ public class SettingsActivity extends Activity * Called when the user selects an item in the header list. The default * implementation will call either * {@link #startWithFragment(String, android.os.Bundle, android.app.Fragment, int, int, CharSequence)} - * or {@link #switchToHeader(com.android.settings.SettingsActivity.Header, boolean, boolean)} + * or {@link #switchToHeader(com.android.settings.SettingsActivity.Header, boolean)} * as appropriate. * * @param header The header that was selected. @@ -1580,7 +1600,7 @@ public class SettingsActivity extends Activity private void onHeaderClick(Header header) { if (header == null) return; if (header.fragment != null) { - switchToHeader(header, false, false); + switchToHeader(header, false); } else if (header.intent != null) { startActivity(header.intent); } diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java index d5bfce20ebf..357183fcc19 100644 --- a/src/com/android/settings/print/PrintServiceSettingsFragment.java +++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java @@ -328,6 +328,14 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED); mToggleSwitch.setCheckedInternal(enabled); + // Title. + SettingsActivity activity = (SettingsActivity) getActivity(); + if (!activity.onIsHidingHeaders()) { + mOldActivityTitle = getActivity().getTitle(); + String title = arguments.getString(PrintSettingsFragment.EXTRA_TITLE); + getActivity().getActionBar().setTitle(title); + } + // Settings title and intent. String settingsTitle = arguments.getString(PrintSettingsFragment.EXTRA_SETTINGS_TITLE); String settingsComponentName = arguments.getString( From 3b6cbdc6a29ff4ee3e62d9f203a6ec261f967b1d Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Mon, 10 Feb 2014 17:39:01 -0800 Subject: [PATCH 10/18] Fix bug #12957032 Stability-Sys: Java crash in com.android.settings: java.lang.NullPointerException: ...Attempt to invoke virtual method 'boolean android.os.Handler.sendEmptyMessage(int)' on a null object reference - prevent NPE by checking the nullity of the Handler reference - remove dead code - rename mHandler to sHandler as it is a static Change-Id: I7f4101f860f24b0cd49a4656971e9b54e55c1286 --- .../settings/fuelgauge/BatteryEntry.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java index 4d1fb2f149a..c2bf127eab7 100644 --- a/src/com/android/settings/fuelgauge/BatteryEntry.java +++ b/src/com/android/settings/fuelgauge/BatteryEntry.java @@ -43,7 +43,7 @@ public class BatteryEntry { static final HashMap sUidCache = new HashMap(); static final ArrayList mRequestQueue = new ArrayList(); - static Handler mHandler; + static Handler sHandler; static private class NameAndIconLoader extends Thread { private boolean mAbort = false; @@ -62,7 +62,9 @@ public class BatteryEntry { BatteryEntry be; synchronized (mRequestQueue) { if (mRequestQueue.isEmpty() || mAbort) { - mHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN); + if (sHandler != null) { + sHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN); + } mRequestQueue.clear(); return; } @@ -76,7 +78,7 @@ public class BatteryEntry { private static NameAndIconLoader mRequestThread; public static void startRequestQueue() { - if (mHandler != null) { + if (sHandler != null) { synchronized (mRequestQueue) { if (!mRequestQueue.isEmpty()) { if (mRequestThread != null) { @@ -96,7 +98,7 @@ public class BatteryEntry { if (mRequestThread != null) { mRequestThread.abort(); mRequestThread = null; - mHandler = null; + sHandler = null; } } } @@ -120,7 +122,7 @@ public class BatteryEntry { } public BatteryEntry(Context context, Handler handler, UserManager um, BatterySipper sipper) { - mHandler = handler; + sHandler = handler; this.context = context; this.sipper = sipper; switch (sipper.drainType) { @@ -221,7 +223,7 @@ public class BatteryEntry { } else { //name = packages[0]; } - if (mHandler != null) { + if (sHandler != null) { synchronized (mRequestQueue) { mRequestQueue.add(this); } @@ -248,11 +250,8 @@ public class BatteryEntry { String[] packageLabels = new String[sipper.mPackages.length]; System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length); - int preferredIndex = -1; // Convert package names to user-facing labels where possible for (int i = 0; i < packageLabels.length; i++) { - // Check if package matches preferred package - if (packageLabels[i].equals(name)) preferredIndex = i; try { ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0); CharSequence label = ai.loadLabel(pm); @@ -298,8 +297,8 @@ public class BatteryEntry { utd.icon = icon; utd.packageName = defaultPackageName; sUidCache.put(uidString, utd); - if (mHandler != null) { - mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this)); + if (sHandler != null) { + sHandler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this)); } } } From f282bcf2d416338c3474845dd31c1f13bde36793 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Thu, 27 Feb 2014 15:51:46 -0800 Subject: [PATCH 11/18] Fix Fragment BackStack and Titles Related to bug #12939786 and bug #13223838 - first use Fragment BreadCrumb for managing Titles and Back - consider the first fragment as the initial one (both in the normal case and in the shortcut one) - fix usage of the Fragment BackStack so that in all cases we are returning to the initial Fragment before exiting the App. Change-Id: I96989d14f4e88688747b93ab9fadd96aea214a2c --- .../android/settings/SettingsActivity.java | 164 ++++++------------ 1 file changed, 57 insertions(+), 107 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 9524f7df3fd..fd6c9862d9b 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -62,10 +62,8 @@ import android.support.v4.widget.DrawerLayout; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; -import android.util.Pair; import android.util.TypedValue; import android.util.Xml; -import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -200,6 +198,8 @@ public class SettingsActivity extends Activity private Header mSelectedHeader; private Header mCurrentHeader; + private CharSequence mInitialTitle; + // Show only these settings for restricted users private int[] SETTINGS_FOR_RESTRICTED = { R.id.wireless_section, @@ -314,39 +314,6 @@ public class SettingsActivity extends Activity private final ArrayList
mHeaders = new ArrayList
(); private HeaderAdapter mHeaderAdapter; - static private class TitlePair extends Pair implements Parcelable { - - public TitlePair(Integer first, CharSequence second) { - super(first, second); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(first); - TextUtils.writeToParcel(second, dest, flags); - } - - TitlePair(Parcel in) { - super(in.readInt(), TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)); - } - - public static final Creator CREATOR = new Creator() { - public TitlePair createFromParcel(Parcel source) { - return new TitlePair(source); - } - public TitlePair[] newArray(int size) { - return new TitlePair[size]; - } - }; - } - - private final ArrayList mTitleStack = new ArrayList(); - private DrawerLayout mDrawerLayout; private ListView mDrawer; private ActionBarDrawerToggle mDrawerToggle; @@ -409,7 +376,7 @@ public class SettingsActivity extends Activity if (isFinishing() || mSelectedHeader == null) { return; } - switchToHeader(mSelectedHeader, false); + switchToHeader(mSelectedHeader, false, false); mSelectedHeader = null; } @@ -557,17 +524,8 @@ public class SettingsActivity extends Activity if (savedInstanceState != null) { // We are restarting from a previous saved state; used that to // initialize, instead of starting fresh. - - ArrayList titles = - savedInstanceState.getParcelableArrayList(SAVE_KEY_TITLES_TAG); - if (titles != null) { - mTitleStack.addAll(titles); - } - final int lastTitle = mTitleStack.size() - 1; - if (lastTitle >= 0) { - final TitlePair last = mTitleStack.get(lastTitle); - setTitleFromPair(last); - } + mInitialTitle = getTitle(); + setTitleFromBackStack(); ArrayList
headers = savedInstanceState.getParcelableArrayList(SAVE_KEY_HEADERS_TAG); @@ -579,18 +537,15 @@ public class SettingsActivity extends Activity setSelectedHeader(mHeaders.get(curHeader)); } } - } else { if (initialFragment != null) { // If we are just showing a fragment, we want to run in // new fragment mode, but don't need to compute and show // the headers. - switchToHeader(initialFragment, initialArguments, true); + final int initialTitleResId = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); + mInitialTitle = (initialTitleResId > 0) ? getText(initialTitleResId) : getTitle(); - final int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); - if (initialTitle != 0) { - setTitle(getText(initialTitle)); - } + switchToHeader(initialFragment, initialArguments, true, mInitialTitle); } else { // We need to try to build the headers. onBuildHeaders(mHeaders); @@ -600,7 +555,8 @@ public class SettingsActivity extends Activity // the currently selected preference fragment. if (mHeaders.size() > 0) { Header h = onGetInitialHeader(); - switchToHeader(h, false); + mInitialTitle = getHeaderTitle(h); + switchToHeader(h, false, true); } } } @@ -667,32 +623,30 @@ public class SettingsActivity extends Activity @Override public void onBackStackChanged() { - final int count = getFragmentManager().getBackStackEntryCount() + 1; - TitlePair pair = null; - int last; - while (mTitleStack.size() > count) { - last = mTitleStack.size() - 1; - pair = mTitleStack.remove(last); - } - // Check if we go back - if (pair != null) { - int size = mTitleStack.size(); - if (size > 0) { - last = mTitleStack.size() - 1; - pair = mTitleStack.get(last); - setTitleFromPair(pair); - } - } + setTitleFromBackStack(); } - private void setTitleFromPair(TitlePair pair) { - final CharSequence title; - if (pair.first > 0) { - title = getText(pair.first); - } else { - title = pair.second; + private void setTitleFromBackStack() { + final int count = getFragmentManager().getBackStackEntryCount(); + if (count == 0) { + setTitle(mInitialTitle); + return; + } + FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1); + setTitleFromBackStackEntry(bse); + } + + private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) { + final CharSequence title; + final int titleRes = bse.getBreadCrumbTitleRes(); + if (titleRes > 0) { + title = getText(titleRes); + } else { + title = bse.getBreadCrumbTitle(); + } + if (title != null) { + setTitle(title); } - setTitle(title); } /** @@ -715,10 +669,6 @@ public class SettingsActivity extends Activity } } } - - if (mTitleStack.size() > 0) { - outState.putParcelableList(SAVE_KEY_TITLES_TAG, mTitleStack); - } } @Override @@ -783,9 +733,10 @@ public class SettingsActivity extends Activity * preference fragment. * * @param header The new header to display. - * @param validate true means that the fragment's Header needs to be validated + * @param validate true means that the fragment's Header needs to be validated. + * @param initial true means that it is the initial Header. */ - private void switchToHeader(Header header, boolean validate) { + private void switchToHeader(Header header, boolean validate, boolean initial) { if (header == null) { return; } @@ -799,15 +750,11 @@ public class SettingsActivity extends Activity FragmentManager.POP_BACK_STACK_INCLUSIVE); } else { if (header.fragment != null) { - mTitleStack.clear(); - switchToHeaderInner(header.fragment, header.fragmentArguments, validate); + switchToHeaderInner(header.fragment, header.fragmentArguments, validate, !initial, + getHeaderTitle(header)); setSelectedHeader(header); - final TitlePair pair = new TitlePair(0, getHeaderTitle(header)); - mTitleStack.add(pair); - setTitle(pair.second); } else if (header.intent != null) { setSelectedHeader(header); - mTitleStack.clear(); startActivity(header.intent); } else { throw new IllegalStateException( @@ -861,19 +808,20 @@ public class SettingsActivity extends Activity } /** - * When in two-pane mode, switch the fragment pane to show the given - * preference fragment. + * Switch the fragment pane to show the given preference fragment. * * @param fragmentName The name of the fragment to display. * @param args Optional arguments to supply to the fragment. * @param validate true means that the fragment's Header needs to be validated */ - private void switchToHeader(String fragmentName, Bundle args, boolean validate) { + private void switchToHeader(String fragmentName, Bundle args, boolean validate, + CharSequence title) { setSelectedHeader(null); - switchToHeaderInner(fragmentName, args, validate); + switchToHeaderInner(fragmentName, args, validate, false, title); } - private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate) { + private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate, + boolean addToBackStack, CharSequence title) { getFragmentManager().popBackStack(BACK_STACK_PREFS, FragmentManager.POP_BACK_STACK_INCLUSIVE); if (validate && !isValidFragment(fragmentName)) { @@ -882,8 +830,14 @@ public class SettingsActivity extends Activity } Fragment f = Fragment.instantiate(this, fragmentName, args); FragmentTransaction transaction = getFragmentManager().beginTransaction(); - transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); transaction.replace(R.id.prefs, f); + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); + if (addToBackStack) { + transaction.addToBackStack(BACK_STACK_PREFS); + } + if (title != null) { + transaction.setBreadCrumbTitle(title); + } transaction.commitAllowingStateLoss(); } @@ -1037,6 +991,13 @@ public class SettingsActivity extends Activity */ private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo, int resultRequestCode, int titleRes, CharSequence titleText) { + final CharSequence cs; + if (titleRes != 0) { + cs = getText(titleRes); + } else { + cs = titleText; + } + Fragment f = Fragment.instantiate(this, fragmentName, args); if (resultTo != null) { f.setTargetFragment(resultTo, resultRequestCode); @@ -1045,19 +1006,8 @@ public class SettingsActivity extends Activity transaction.replace(R.id.prefs, f); transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); transaction.addToBackStack(BACK_STACK_PREFS); + transaction.setBreadCrumbTitle(cs); transaction.commitAllowingStateLoss(); - - final TitlePair pair; - final CharSequence cs; - if (titleRes != 0) { - pair = new TitlePair(titleRes, null); - cs = getText(titleRes); - } else { - pair = new TitlePair(0, titleText); - cs = titleText; - } - setTitle(cs); - mTitleStack.add(pair); } /** From 101fbf42ae850cdbd832b4b75fe6c692e2311a1a Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Tue, 4 Mar 2014 12:53:59 -0800 Subject: [PATCH 12/18] Fix bug #13300024 Settings app crashes on changing device orientation - remove crashing code. Basically let the Framework do its work. No need to save the state of the EditText by ourselves. Change-Id: I49e98a852f4fcda61eabaa2967d027942905ec27 --- .../settings/dashboard/DashboardSummary.java | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java index ce3b0c0440c..722cefddd30 100644 --- a/src/com/android/settings/dashboard/DashboardSummary.java +++ b/src/com/android/settings/dashboard/DashboardSummary.java @@ -40,8 +40,6 @@ import com.android.settings.indexer.Index; public class DashboardSummary extends Fragment { - private static final String SAVE_KEY_QUERY = ":settings:query"; - private EditText mEditText; private ListView mListView; @@ -90,26 +88,6 @@ public class DashboardSummary extends Fragment { updateSearchResults(); } - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if (outState != null) { - outState.putString(SAVE_KEY_QUERY, mEditText.getText().toString()); - } - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - if (savedInstanceState != null) { - final String query = savedInstanceState.getString(SAVE_KEY_QUERY); - if (query != null && !TextUtils.isEmpty(query)) { - mEditText.setText(query); - } - } - } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { From 35321beb706b882959ee46bc3561513c2b8e434f Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Mon, 10 Mar 2014 12:18:39 -0700 Subject: [PATCH 13/18] Fix bug #13394626 Settings app crashes on changing orientation to landscape mode - fix NPE on mInitialHeader.id Change-Id: Ic1017f5a8a20755bf7f36b1f3406d45dcc80ae8f --- src/com/android/settings/SettingsActivity.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index ec4ebc73855..8582bc67ab8 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -133,7 +133,6 @@ public class SettingsActivity extends Activity // Constants for state save/restore private static final String SAVE_KEY_HEADERS_TAG = ":settings:headers"; private static final String SAVE_KEY_CURRENT_HEADER_TAG = ":settings:cur_header"; - private static final String SAVE_KEY_TITLES_TAG = ":settings:titles"; /** * When starting this activity, the invoking Intent can contain this extra @@ -587,7 +586,6 @@ public class SettingsActivity extends Activity // We are restarting from a previous saved state; used that to // initialize, instead of starting fresh. mInitialTitle = getTitle(); - setTitleFromBackStack(); ArrayList
headers = savedInstanceState.getParcelableArrayList(SAVE_KEY_HEADERS_TAG); @@ -599,6 +597,7 @@ public class SettingsActivity extends Activity setSelectedHeader(mHeaders.get(curHeader)); mInitialHeader = mCurrentHeader; } + setTitleFromBackStack(); } } else { String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT); @@ -713,18 +712,23 @@ public class SettingsActivity extends Activity @Override public void onBackStackChanged() { - setTitleFromBackStack(); + if (setTitleFromBackStack() == 0) { + setSelectedHeaderById(mInitialHeader.id); + } } - private void setTitleFromBackStack() { + private int setTitleFromBackStack() { final int count = getFragmentManager().getBackStackEntryCount(); + if (count == 0) { setTitle(mInitialTitle); - setSelectedHeaderById(mInitialHeader.id); - return; + return 0; } + FragmentManager.BackStackEntry bse = getFragmentManager().getBackStackEntryAt(count - 1); setTitleFromBackStackEntry(bse); + + return count; } private void setTitleFromBackStackEntry(FragmentManager.BackStackEntry bse) { From 3107759662080ba02caf15b7ebb68a0e81fd696b Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Thu, 20 Mar 2014 12:24:57 -0700 Subject: [PATCH 14/18] Fix bug #13563247 Settings crash on launch in secondary user - add missing permission android.permission.READ_SEARCH_INDEXABLES Change-Id: I577f8bfebf5e29e7954ca36cf65e981464aa5924 --- AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index c22d96f6924..9c9b237d120 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -67,6 +67,7 @@ + Date: Thu, 3 Apr 2014 13:57:56 -0700 Subject: [PATCH 15/18] Re-enable on/off switch for Wi-Fi and Bluetooth Settings - the switch was no more there when launching from an Intent (it was a regression) Change-Id: I1fc95cad4523a1d3812323fb26908f925a9e623e --- .../settings/bluetooth/BluetoothSettings.java | 14 ++++++-------- src/com/android/settings/wifi/WifiSettings.java | 7 ++----- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java index 624b3188f17..7068bc769bf 100755 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -129,14 +129,12 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem final SettingsActivity activity = (SettingsActivity) getActivity(); - if (activity.onIsHidingHeaders()) { - activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, - ActionBar.DISPLAY_SHOW_CUSTOM); - activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams( - ActionBar.LayoutParams.WRAP_CONTENT, - ActionBar.LayoutParams.WRAP_CONTENT, - Gravity.CENTER_VERTICAL | Gravity.END)); - } + activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, + ActionBar.DISPLAY_SHOW_CUSTOM); + activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams( + ActionBar.LayoutParams.WRAP_CONTENT, + ActionBar.LayoutParams.WRAP_CONTENT, + Gravity.CENTER_VERTICAL | Gravity.END)); } @Override diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index 21fecd34551..43f9f759543 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -412,12 +412,9 @@ public class WifiSettings extends RestrictedSettingsFragment final Activity activity = getActivity(); mSwitch = new Switch(activity); - boolean addSwitch = false; + boolean addSwitch = true; - if (activity instanceof SettingsActivity) { - SettingsActivity sa = (SettingsActivity) activity; - addSwitch = sa.onIsHidingHeaders(); - } else if (activity instanceof WifiPickerActivity) { + if (activity instanceof WifiPickerActivity) { PreferenceActivity pa = (PreferenceActivity) activity; addSwitch = pa.onIsHidingHeaders(); } From aa448bade6b0ca31132884009ea204b4422c3e71 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Thu, 3 Apr 2014 16:43:26 -0700 Subject: [PATCH 16/18] Fix bug #13794200 Settings crash when screen is locked and Power Usage... ...Settings is launched with an Intent - fix the NPE by checking if mSearchMenuItem / mSearchView references are null Change-Id: I7518c8360af88a20df780be8cb89360a26cdb8d0 --- src/com/android/settings/SettingsActivity.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 5aa273787fb..62b37af72ba 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -185,6 +185,8 @@ public class SettingsActivity extends Activity private static final String EXTRA_UI_OPTIONS = "settings:ui_options"; + private static final String EMPTY_QUERY = ""; + private static boolean sShowNoHomeNotice = false; private String mFragmentClass; @@ -577,8 +579,17 @@ public class SettingsActivity extends Activity } } } - outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, mSearchMenuItem.isActionViewExpanded()); - outState.putString(SAVE_KEY_SEARCH_QUERY, mSearchView.getQuery().toString()); + + // The option menus are created if the ActionBar is visible and they are also created + // asynchronously. If you launch Settings with an Intent action like + // android.intent.action.POWER_USAGE_SUMMARY and at the same time your device is locked + // thru a LockScreen, onCreateOptionsMenu() is not yet called and references to the search + // menu item and search view are null. + boolean isExpanded = (mSearchMenuItem != null) && mSearchMenuItem.isActionViewExpanded(); + outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, isExpanded); + + String query = (mSearchView != null) ? mSearchView.getQuery().toString() : EMPTY_QUERY; + outState.putString(SAVE_KEY_SEARCH_QUERY, query); } @Override From 0c19d9e9c8ffef4161a7ea3d55755c5b34c9768f Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Fri, 4 Apr 2014 10:16:59 -0700 Subject: [PATCH 17/18] Add more logging for onHeaderClick(...) - log Header title and position Change-Id: I07f7e8c50613b97609a3ea462b7a8e8fcc415f70 --- src/com/android/settings/SettingsActivity.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 62b37af72ba..0996c5bdd19 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -647,8 +647,9 @@ public class SettingsActivity extends Activity * preference fragment. * * @param header The new header to display. + * @param position The position of the Header in the list. */ - private void onHeaderClick(Header header) { + private void onHeaderClick(Header header, int position) { if (header == null) { return; } @@ -658,6 +659,9 @@ public class SettingsActivity extends Activity } else if (header.intent != null) { startActivity(header.intent); } else { + String title = header.getTitle(getResources()).toString(); + Log.e(LOG_TAG, "Can't switch to header that has no Fragment nor Intent. Title: " + + title + " Position: " + position); throw new IllegalStateException( "Can't switch to header that has no Fragment nor Intent"); } @@ -1213,7 +1217,7 @@ public class SettingsActivity extends Activity Object item = mHeaderAdapter.getItem(position); if (item instanceof Header) { mSelectedHeader = (Header) item; - onHeaderClick(mSelectedHeader); + onHeaderClick(mSelectedHeader, position); revertToInitialFragment(); } } From d26a424d1879bed937ce4eb157961b2535fab692 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Tue, 8 Apr 2014 13:35:06 -0700 Subject: [PATCH 18/18] Fix bug #13744434 Stability: ISE in Settings: Can't switch to header... ..that has no Fragment nor Intent at SettingsActivity.onHeaderClick(SettingsActivity.java:654) - satisfy the Monkeys has they were able to click on "WIRELESS & NETWORK" header which is a Category and normally non clickable... (so probably a race condition) Change-Id: Ia33d2b6e55e910409a566e5f05c1e3bae8008807 --- src/com/android/settings/SettingsActivity.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 7cdf78176a0..312ce744210 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -654,12 +654,6 @@ public class SettingsActivity extends Activity header.getTitle(getResources())); } else if (header.intent != null) { startActivity(header.intent); - } else { - String title = header.getTitle(getResources()).toString(); - Log.e(LOG_TAG, "Can't switch to header that has no Fragment nor Intent. Title: " + - title + " Position: " + position); - throw new IllegalStateException( - "Can't switch to header that has no Fragment nor Intent"); } }