cmparts: Use the preferences support library

 * So we can mimic Settings exactly

Change-Id: I87bed4794df983c6e3f8c6c80dfd4de2debf9358
diff --git a/Android.mk b/Android.mk
index 0ffb101..07894b5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,10 +4,36 @@
 
 LOCAL_PACKAGE_NAME := CMParts
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := org.cyanogenmod.platform.internal
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-v4 \
+    android-support-v13 \
+    android-support-v7-recyclerview \
+    android-support-v7-preference \
+    android-support-v7-appcompat \
+    android-support-v14-preference \
+    jsr305 \
+    org.cyanogenmod.platform.internal
+
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/res \
+    frameworks/support/v7/preference/res \
+    frameworks/support/v14/preference/res \
+    frameworks/support/v7/appcompat/res \
+    frameworks/support/v7/recyclerview/res
+
+LOCAL_AAPT_FLAGS := --auto-add-overlay \
+    --extra-packages android.support.v7.preference:android.support.v14.preference:android.support.v17.preference:android.support.v7.appcompat:android.support.v7.recyclerview
+
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 LOCAL_MODULE_TAGS := optional
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
+ifneq ($(INCREMENTAL_BUILDS),)
+    LOCAL_PROGUARD_ENABLED := disabled
+    LOCAL_JACK_ENABLED := incremental
+    LOCAL_DX_FLAGS := --multi-dex
+    LOCAL_JACK_FLAGS := --multi-dex native
+endif
+
 include $(BUILD_PACKAGE)
diff --git a/res/layout/layout_preference_frame.xml b/res/layout/layout_preference_frame.xml
new file mode 100644
index 0000000..eec3d7a
--- /dev/null
+++ b/res/layout/layout_preference_frame.xml
@@ -0,0 +1,18 @@
+<!--
+     Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" />
diff --git a/res/layout/loading_container.xml b/res/layout/loading_container.xml
new file mode 100644
index 0000000..5a165de
--- /dev/null
+++ b/res/layout/loading_container.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/loading_container"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:visibility="gone"
+    android:gravity="center">
+
+    <ProgressBar style="?android:attr/progressBarStyleLarge"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+    <TextView android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:text="@string/loading"
+        android:paddingTop="4dip"
+        android:singleLine="true" />
+
+</LinearLayout>
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
new file mode 100644
index 0000000..2e51e47
--- /dev/null
+++ b/res/layout/preference_list_fragment.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container_material"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/transparent">
+
+    <FrameLayout android:id="@+id/pinned_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+    <FrameLayout
+        android:id="@android:id/list_container"
+        android:layout_height="0px"
+        android:layout_weight="1"
+        android:layout_width="match_parent"
+        android:paddingStart="@dimen/settings_side_margin"
+        android:paddingEnd="@dimen/settings_side_margin">
+
+        <ListView android:id="@+id/backup_list"
+            style="@style/PreferenceFragmentListSinglePane"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:paddingTop="@dimen/dashboard_padding_top"
+            android:paddingBottom="@dimen/dashboard_padding_bottom"
+            android:scrollbarStyle="@*android:integer/preference_fragment_scrollbarStyle"
+            android:clipToPadding="false"
+            android:drawSelectorOnTop="false"
+            android:elevation="@dimen/dashboard_category_elevation"
+            android:visibility="gone"
+            android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+        <include layout="@layout/loading_container" />
+
+    </FrameLayout>
+
+    <TextView android:id="@android:id/empty"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:padding="@*android:dimen/preference_fragment_padding_side"
+        android:layout_gravity="center"
+        android:gravity="center_vertical"
+        android:visibility="gone" />
+
+    <RelativeLayout android:id="@+id/button_bar"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_weight="0"
+        android:visibility="gone">
+
+        <Button android:id="@+id/back_button"
+            android:layout_width="150dip"
+            android:layout_height="wrap_content"
+            android:layout_margin="5dip"
+            android:layout_alignParentStart="true"
+            android:text="@*android:string/back_button_label"
+            />
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentEnd="true">
+
+            <Button android:id="@+id/skip_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:text="@*android:string/skip_button_label"
+                android:visibility="gone"
+                />
+
+            <Button android:id="@+id/next_button"
+                android:layout_width="150dip"
+                android:layout_height="wrap_content"
+                android:layout_margin="5dip"
+                android:text="@*android:string/next_button_label"
+                />
+
+        </LinearLayout>
+
+    </RelativeLayout>
+
+</LinearLayout>
+
diff --git a/res/layout/preference_material_settings.xml b/res/layout/preference_material_settings.xml
new file mode 100644
index 0000000..b8a00f2
--- /dev/null
+++ b/res/layout/preference_material_settings.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Based off frameworks/base/core/res/res/layout/preference_material.xml
+     except that this has the negative margin on the image removed. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:clipToPadding="false">
+
+    <LinearLayout
+        android:id="@id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:minWidth="60dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <com.android.internal.widget.PreferenceImageView
+            android:id="@android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:maxWidth="48dp"
+            android:maxHeight="48dp" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp">
+
+        <TextView android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:ellipsize="marquee" />
+
+        <TextView android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:gravity="end|center_vertical"
+        android:paddingStart="16dp"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a14d36b..a10b307 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -15,9 +15,22 @@
 -->
 
 <resources>
+
     <!-- ActionBar height -->
     <dimen name="actionbar_size">56dip</dimen>
 
+    <!-- ActionBar contentInsetStart -->
+    <dimen name="actionbar_contentInsetStart">16dp</dimen>
+
+    <!-- Dashboard padding in its container -->
+    <dimen name="dashboard_padding_start">0dp</dimen>
+    <dimen name="dashboard_padding_end">0dp</dimen>
+    <dimen name="dashboard_padding_top">0dp</dimen>
+    <dimen name="dashboard_padding_bottom">0dp</dimen>
+
+    <!-- Dashboard category panel elevation -->
+    <dimen name="dashboard_category_elevation">2dp</dimen>
+
     <dimen name="settings_side_margin">0dip</dimen>
 
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 7835732..f810add 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -15,6 +15,18 @@
 -->     
 
 <resources>
+    <style name="Preference">
+        <item name="android:layout">@layout/preference_material_settings</item>
+    </style>
+
+    <style name="EditTextPreference" parent="@*android:style/Preference.Material.DialogPreference.EditTextPreference">
+        <item name="android:dialogLayout">@layout/preference_dialog_edittext</item>
+    </style>
+
+    <style name="PreferenceFragmentStyle" parent="@*android:style/PreferenceFragment.Material">
+        <item name="android:layout">@layout/preference_list_fragment</item>
+    </style>
+
     <style name="PreferenceHeaderPanelSinglePane">
         <item name="android:layout_marginStart">0dp</item>
         <item name="android:layout_marginEnd">0dp</item>
@@ -50,5 +62,21 @@
         <item name="android:scrollbarStyle">outsideOverlay</item>
     </style>
 
- 
+    <style name="SettingsPreferenceHeaderPanel" parent="@*android:style/PreferenceHeaderPanel">
+    </style>
+
+    <style name="SettingsPreferenceHeaderList" parent="@*android:style/PreferenceHeaderList">
+    </style>
+
+    <style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium" />
+    <style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small" />
+    <style name="TextAppearance.Switch" parent="@android:style/TextAppearance.Material.Title" />
+
+    <style name="TextAppearance.CategoryTitle" parent="@android:style/TextAppearance.Material.Body2">
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
+    </style>
+
+    <style name="TextAppearance.TileTitle" parent="@android:style/TextAppearance.Material.Subhead" />
+    <style name="TextAppearance.TileSubTitle" parent="@android:style/TextAppearance.Material.Body1" />
+
 </resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 8c10990..e575ba4 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -15,9 +15,33 @@
 -->
 
 <resources>
+    <style name="Theme.ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid">
+        <item name="android:contentInsetStart">@dimen/actionbar_contentInsetStart</item>
+    </style>
+
+    <style name="ThemeOverlay.AlertDialog" parent="@android:style/ThemeOverlay.Material.Dialog.Alert">
+        <item name="android:windowSoftInputMode">adjustResize</item>
+    </style>
+
+    <style name="Theme.AlertDialog" parent="@*android:style/Theme.Material.Settings.Dialog.Alert">
+        <item name="android:windowSoftInputMode">adjustResize</item>
+
+        <!-- Redefine the ActionBar style for contentInsetStart -->
+        <item name="android:actionBarStyle">@style/Theme.ActionBar</item>
+    </style>
+
+    <style name="PreferenceTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+        <item name="@android:preferenceStyle">@style/Preference</item>
+        <item name="@android:editTextPreferenceStyle">@style/EditTextPreference</item>
+        <item name="@dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
+        <item name="@android:preferenceFragmentStyle">@style/PreferenceFragmentStyle</item>
+    </style>
+
     <style name="Theme.SettingsBase" parent="@android:style/Theme.Material.Settings" />
 
+
     <style name="Theme.Settings" parent="Theme.SettingsBase">
+        <item name="preferenceTheme">@style/PreferenceTheme</item>
         <item name="@*android:preferenceHeaderPanelStyle">@style/PreferenceHeaderPanelSinglePane</item>
         <item name="@*android:preferencePanelStyle">@style/PreferencePanelSinglePane</item>
         <item name="@*android:preferenceListStyle">@style/PreferenceHeaderListSinglePane</item>
@@ -25,9 +49,21 @@
         <item name="@*android:preferenceFragmentPaddingSide">@dimen/settings_side_margin</item>
 
         <!-- Redefine the ActionBar style for contentInsetStart -->
+        <item name="android:actionBarStyle">@style/Theme.ActionBar</item>
         <item name="@*android:actionBarSize">@dimen/actionbar_size</item>
 
         <item name="preferenceBackgroundColor">@drawable/preference_background</item>
-	</style>
+
+        <!-- For all Alert Dialogs -->
+        <item name="android:alertDialogTheme">@style/Theme.AlertDialog</item>
+    </style>
+
+    <style name="Theme.DialogWhenLarge" parent="@*android:style/Theme.Material.Settings.DialogWhenLarge">
+        <!-- Redefine the ActionBar style for contentInsetStart -->
+        <item name="android:actionBarStyle">@style/Theme.ActionBar</item>
+
+        <item name="preferenceBackgroundColor">@drawable/preference_background</item>
+    </style>
+
 </resources>
 
diff --git a/src/org/cyanogenmod/cmparts/CMGlobalSettingSwitchPreference.java b/src/org/cyanogenmod/cmparts/CMGlobalSettingSwitchPreference.java
index 7b2d2d9..4190bf8 100644
--- a/src/org/cyanogenmod/cmparts/CMGlobalSettingSwitchPreference.java
+++ b/src/org/cyanogenmod/cmparts/CMGlobalSettingSwitchPreference.java
@@ -17,7 +17,7 @@
 package org.cyanogenmod.cmparts;
 
 import android.content.Context;
-import android.preference.SwitchPreference;
+import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
 
 import cyanogenmod.providers.CMSettings;
@@ -56,10 +56,4 @@
         return CMSettings.Global.getInt(getContext().getContentResolver(),
                 getKey(), defaultReturnValue ? 1 : 0) != 0;
     }
-
-    protected boolean isPersisted() {
-        // Using getString instead of getInt so we can simply check for null
-        // instead of catching an exception. (All values are stored as strings.)
-        return CMSettings.Global.getString(getContext().getContentResolver(), getKey()) != null;
-    }
 }
diff --git a/src/org/cyanogenmod/cmparts/CMSecureSettingSwitchPreference.java b/src/org/cyanogenmod/cmparts/CMSecureSettingSwitchPreference.java
index 1f0d72a..2226e79 100644
--- a/src/org/cyanogenmod/cmparts/CMSecureSettingSwitchPreference.java
+++ b/src/org/cyanogenmod/cmparts/CMSecureSettingSwitchPreference.java
@@ -17,7 +17,7 @@
 package org.cyanogenmod.cmparts;
 
 import android.content.Context;
-import android.preference.SwitchPreference;
+import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
 
 import cyanogenmod.providers.CMSettings;
diff --git a/src/org/cyanogenmod/cmparts/CMSystemSettingSwitchPreference.java b/src/org/cyanogenmod/cmparts/CMSystemSettingSwitchPreference.java
index 92c3622..fa0acce 100644
--- a/src/org/cyanogenmod/cmparts/CMSystemSettingSwitchPreference.java
+++ b/src/org/cyanogenmod/cmparts/CMSystemSettingSwitchPreference.java
@@ -17,7 +17,7 @@
 package org.cyanogenmod.cmparts;
 
 import android.content.Context;
-import android.preference.SwitchPreference;
+import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
 
 import cyanogenmod.providers.CMSettings;
@@ -56,10 +56,4 @@
         return CMSettings.System.getInt(getContext().getContentResolver(),
                 getKey(), defaultReturnValue ? 1 : 0) != 0;
     }
-
-    protected boolean isPersisted() {
-        // Using getString instead of getInt so we can simply check for null
-        // instead of catching an exception. (All values are stored as strings.)
-        return CMSettings.System.getString(getContext().getContentResolver(), getKey()) != null;
-    }
 }
diff --git a/src/org/cyanogenmod/cmparts/CustomDialogPreference.java b/src/org/cyanogenmod/cmparts/CustomDialogPreference.java
new file mode 100644
index 0000000..fc25b1f
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/CustomDialogPreference.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.cyanogenmod.cmparts;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceDialogFragment;
+import android.support.v7.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class CustomDialogPreference extends DialogPreference {
+
+    private CustomPreferenceDialogFragment mFragment;
+
+    public CustomDialogPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public CustomDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public CustomDialogPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public CustomDialogPreference(Context context) {
+        super(context);
+    }
+
+    public boolean isDialogOpen() {
+        return getDialog() != null && getDialog().isShowing();
+    }
+
+    public Dialog getDialog() {
+        return mFragment != null ? mFragment.getDialog() : null;
+    }
+
+    protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+            DialogInterface.OnClickListener listener) {
+    }
+
+    protected void onDialogClosed(boolean positiveResult) {
+    }
+
+    protected void onClick(DialogInterface dialog, int which) {
+    }
+
+    protected void onBindDialogView(View view) {
+    }
+
+    private void setFragment(CustomPreferenceDialogFragment fragment) {
+        mFragment = fragment;
+    }
+
+    public static class CustomPreferenceDialogFragment extends PreferenceDialogFragment {
+
+        public static CustomPreferenceDialogFragment newInstance(String key) {
+            final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+            final Bundle b = new Bundle(1);
+            b.putString(ARG_KEY, key);
+            fragment.setArguments(b);
+            return fragment;
+        }
+
+        private CustomDialogPreference getCustomizablePreference() {
+            return (CustomDialogPreference) getPreference();
+        }
+
+        @Override
+        protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+            super.onPrepareDialogBuilder(builder);
+            getCustomizablePreference().setFragment(this);
+            getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+        }
+
+        @Override
+        public void onDialogClosed(boolean positiveResult) {
+            getCustomizablePreference().onDialogClosed(positiveResult);
+        }
+
+        @Override
+        protected void onBindDialogView(View view) {
+            super.onBindDialogView(view);
+            getCustomizablePreference().onBindDialogView(view);
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            super.onClick(dialog, which);
+            getCustomizablePreference().onClick(dialog, which);
+        }
+    }
+}
diff --git a/src/org/cyanogenmod/cmparts/LayoutPreference.java b/src/org/cyanogenmod/cmparts/LayoutPreference.java
new file mode 100644
index 0000000..5e9786b
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/LayoutPreference.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.cmparts;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+public class LayoutPreference extends Preference {
+
+    private View mRootView;
+
+    public LayoutPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, com.android.internal.R.styleable.Preference, 0, 0);
+        int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
+                0);
+        if (layoutResource == 0) {
+            throw new IllegalArgumentException("LayoutPreference requires a layout to be defined");
+        }
+        // Need to create view now so that findViewById can be called immediately.
+        final View view = LayoutInflater.from(getContext())
+                .inflate(layoutResource, null, false);
+        setView(view);
+    }
+
+    public LayoutPreference(Context context, int resource) {
+        this(context, LayoutInflater.from(context).inflate(resource, null, false));
+    }
+
+    public LayoutPreference(Context context, View view) {
+        super(context);
+        setView(view);
+    }
+
+    private void forceCustomPadding(View view, boolean additive) {
+        final Resources res = view.getResources();
+        final int paddingSide = res.getDimensionPixelSize(R.dimen.settings_side_margin);
+
+        final int paddingStart = paddingSide + (additive ? view.getPaddingStart() : 0);
+        final int paddingEnd = paddingSide + (additive ? view.getPaddingEnd() : 0);
+        final int paddingBottom = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.preference_fragment_padding_bottom);
+
+        view.setPaddingRelative(paddingStart, 0, paddingEnd, paddingBottom);
+    }
+
+    private void setView(View view) {
+        setLayoutResource(R.layout.layout_preference_frame);
+        setSelectable(false);
+        //final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
+        //if (allDetails != null) {
+        //    forceCustomPadding(allDetails, true /* additive padding */);
+        //}
+        mRootView = view;
+        setShouldDisableView(false);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder view) {
+        FrameLayout layout = (FrameLayout) view.itemView;
+        layout.removeAllViews();
+        ViewGroup parent = (ViewGroup) mRootView.getParent();
+        if (parent != null) {
+            parent.removeView(mRootView);
+        }
+        layout.addView(mRootView);
+    }
+
+    public View findViewById(int id) {
+        return mRootView.findViewById(id);
+    }
+
+}
diff --git a/src/org/cyanogenmod/cmparts/SelfAvailablePreference.java b/src/org/cyanogenmod/cmparts/SelfAvailablePreference.java
new file mode 100644
index 0000000..58afc90
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/SelfAvailablePreference.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.cmparts;
+
+import android.content.Context;
+
+/**
+ * Interface for classes whose instances can provide the availability of the preference.
+ */
+public interface SelfAvailablePreference {
+    /**
+     * @return the availability of the preference. Please make sure the availability in managed
+     * profile is taken into account.
+     */
+    boolean isAvailable(Context context);
+}
diff --git a/src/org/cyanogenmod/cmparts/SettingsPreferenceFragment.java b/src/org/cyanogenmod/cmparts/SettingsPreferenceFragment.java
index 73811e3..f2825e5 100644
--- a/src/org/cyanogenmod/cmparts/SettingsPreferenceFragment.java
+++ b/src/org/cyanogenmod/cmparts/SettingsPreferenceFragment.java
@@ -1,6 +1,5 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2016 The CyanogenMod Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,24 +16,437 @@
 
 package org.cyanogenmod.cmparts;
 
+import android.app.Activity;
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.app.Fragment;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
+import android.support.annotation.XmlRes;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.preference.PreferenceGroupAdapter;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.view.animation.*;
 
+import java.util.UUID;
+
+/**
+ * Base class for Settings fragments, with some helper functions and dialog management.
+ */
 public abstract class SettingsPreferenceFragment extends PreferenceFragment
         implements DialogCreatable {
 
-    private static final String TAG = "SettingsPreferenceFragment";
+    /**
+     * The Help Uri Resource key. This can be passed as an extra argument when creating the
+     * Fragment.
+     **/
+    public static final String HELP_URI_RESOURCE_KEY = "help_uri_resource";
+
+    private static final String TAG = "SettingsPreference";
+
+    private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
+
+    private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted";
 
     private SettingsDialogFragment mDialogFragment;
 
+    private String mHelpUri;
+
+    private static final int ORDER_FIRST = -1;
+    private static final int ORDER_LAST = Integer.MAX_VALUE -1;
+
+    // Cache the content resolver for async callbacks
+    private ContentResolver mContentResolver;
+
+    private String mPreferenceKey;
+    private boolean mPreferenceHighlighted = false;
+
+    private RecyclerView.Adapter mCurrentRootAdapter;
+    private boolean mIsDataSetObserverRegistered = false;
+    private RecyclerView.AdapterDataObserver mDataSetObserver =
+            new RecyclerView.AdapterDataObserver() {
+        @Override
+        public void onChanged() {
+            onDataSetChanged();
+        }
+    };
+
+    private ViewGroup mPinnedHeaderFrameLayout;
+    private ViewGroup mButtonBar;
+
+    private LayoutPreference mHeader;
+
+    private LayoutPreference mFooter;
+    private View mEmptyView;
+    private LinearLayoutManager mLayoutManager;
+    private HighlightablePreferenceGroupAdapter mAdapter;
+    private ArrayMap<String, Preference> mPreferenceCache;
+    private boolean mAnimationAllowed;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        if (icicle != null) {
+            mPreferenceHighlighted = icicle.getBoolean(SAVE_HIGHLIGHTED_KEY);
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View root = super.onCreateView(inflater, container, savedInstanceState);
+        mPinnedHeaderFrameLayout = (ViewGroup) root.findViewById(R.id.pinned_header);
+        mButtonBar = (ViewGroup) root.findViewById(R.id.button_bar);
+        return root;
+    }
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+    }
+
+    @Override
+    public void addPreferencesFromResource(@XmlRes int preferencesResId) {
+        super.addPreferencesFromResource(preferencesResId);
+        checkAvailablePrefs(getPreferenceScreen());
+    }
+
+    private void checkAvailablePrefs(PreferenceGroup preferenceGroup) {
+        if (preferenceGroup == null) return;
+        for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) {
+            Preference pref = preferenceGroup.getPreference(i);
+            if (pref instanceof SelfAvailablePreference
+                    && !((SelfAvailablePreference) pref).isAvailable(getContext())) {
+                preferenceGroup.removePreference(pref);
+            } else if (pref instanceof PreferenceGroup) {
+                checkAvailablePrefs((PreferenceGroup) pref);
+            }
+        }
+    }
+
+    public ViewGroup getButtonBar() {
+        return mButtonBar;
+    }
+
+    public View setPinnedHeaderView(int layoutResId) {
+        final LayoutInflater inflater = getActivity().getLayoutInflater();
+        final View pinnedHeader =
+                inflater.inflate(layoutResId, mPinnedHeaderFrameLayout, false);
+        setPinnedHeaderView(pinnedHeader);
+        return pinnedHeader;
+    }
+
+    public void setPinnedHeaderView(View pinnedHeader) {
+        mPinnedHeaderFrameLayout.addView(pinnedHeader);
+        mPinnedHeaderFrameLayout.setVisibility(View.VISIBLE);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mPreferenceHighlighted);
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        setHasOptionsMenu(true);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        final Bundle args = getArguments();
+        if (args != null) {
+            mPreferenceKey = args.getString(PartsActivity.EXTRA_FRAGMENT_ARG_KEY);
+            highlightPreferenceIfNeeded();
+        }
+    }
+
+    @Override
+    protected void onBindPreferences() {
+        registerObserverIfNeeded();
+    }
+
+    @Override
+    protected void onUnbindPreferences() {
+        unregisterObserverIfNeeded();
+    }
+
+    public void showLoadingWhenEmpty() {
+        View loading = getView().findViewById(R.id.loading_container);
+        setEmptyView(loading);
+    }
+
+    public void handleLoadingContainer(View loading, View doneLoading, boolean done,
+                                              boolean animate) {
+        setViewShown(loading, !done, animate);
+        setViewShown(doneLoading, done, animate);
+    }
+
+    private void setViewShown(final View view, boolean shown, boolean animate) {
+        if (animate) {
+            Animation animation = AnimationUtils.loadAnimation(view.getContext(),
+                    shown ? android.R.anim.fade_in : android.R.anim.fade_out);
+            if (shown) {
+                view.setVisibility(View.VISIBLE);
+            } else {
+                animation.setAnimationListener(new Animation.AnimationListener() {
+                    @Override
+                    public void onAnimationStart(Animation animation) {
+                    }
+
+                    @Override
+                    public void onAnimationRepeat(Animation animation) {
+                    }
+
+                    @Override
+                    public void onAnimationEnd(Animation animation) {
+                        view.setVisibility(View.INVISIBLE);
+                    }
+                });
+            }
+            view.startAnimation(animation);
+        } else {
+            view.clearAnimation();
+            view.setVisibility(shown ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
+
+    public void setLoading(boolean loading, boolean animate) {
+        View loading_container = getView().findViewById(R.id.loading_container);
+        handleLoadingContainer(loading_container, getListView(), !loading, animate);
+    }
+
+    public void registerObserverIfNeeded() {
+        if (!mIsDataSetObserverRegistered) {
+            if (mCurrentRootAdapter != null) {
+                mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver);
+            }
+            mCurrentRootAdapter = getListView().getAdapter();
+            mCurrentRootAdapter.registerAdapterDataObserver(mDataSetObserver);
+            mIsDataSetObserverRegistered = true;
+            onDataSetChanged();
+        }
+    }
+
+    public void unregisterObserverIfNeeded() {
+        if (mIsDataSetObserverRegistered) {
+            if (mCurrentRootAdapter != null) {
+                mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver);
+                mCurrentRootAdapter = null;
+            }
+            mIsDataSetObserverRegistered = false;
+        }
+    }
+
+    public void highlightPreferenceIfNeeded() {
+        if (isAdded() && !mPreferenceHighlighted &&!TextUtils.isEmpty(mPreferenceKey)) {
+            highlightPreference(mPreferenceKey);
+        }
+    }
+
+    protected void onDataSetChanged() {
+        highlightPreferenceIfNeeded();
+        updateEmptyView();
+    }
+
+    public LayoutPreference getHeaderView() {
+        return mHeader;
+    }
+
+    public LayoutPreference getFooterView() {
+        return mFooter;
+    }
+
+    protected void setHeaderView(int resource) {
+        mHeader = new LayoutPreference(getPrefContext(), resource);
+        addPreferenceToTop(mHeader);
+    }
+
+    protected void setHeaderView(View view) {
+        mHeader = new LayoutPreference(getPrefContext(), view);
+        addPreferenceToTop(mHeader);
+    }
+
+    private void addPreferenceToTop(LayoutPreference preference) {
+        preference.setOrder(ORDER_FIRST);
+        if (getPreferenceScreen() != null) {
+            getPreferenceScreen().addPreference(preference);
+        }
+    }
+
+    protected void setFooterView(int resource) {
+        setFooterView(resource != 0 ? new LayoutPreference(getPrefContext(), resource) : null);
+    }
+
+    protected void setFooterView(View v) {
+        setFooterView(v != null ? new LayoutPreference(getPrefContext(), v) : null);
+    }
+
+    private void setFooterView(LayoutPreference footer) {
+        if (getPreferenceScreen() != null && mFooter != null) {
+            getPreferenceScreen().removePreference(mFooter);
+        }
+        if (footer != null) {
+            mFooter = footer;
+            mFooter.setOrder(ORDER_LAST);
+            if (getPreferenceScreen() != null) {
+                getPreferenceScreen().addPreference(mFooter);
+            }
+        } else {
+            mFooter = null;
+        }
+    }
+
+    @Override
+    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
+        if (preferenceScreen != null && !preferenceScreen.isAttached()) {
+            // Without ids generated, the RecyclerView won't animate changes to the preferences.
+            preferenceScreen.setShouldUseGeneratedIds(mAnimationAllowed);
+        }
+        super.setPreferenceScreen(preferenceScreen);
+        if (preferenceScreen != null) {
+            if (mHeader != null) {
+                preferenceScreen.addPreference(mHeader);
+            }
+            if (mFooter != null) {
+                preferenceScreen.addPreference(mFooter);
+            }
+        }
+    }
+
+    private void updateEmptyView() {
+        if (mEmptyView == null) return;
+        if (getPreferenceScreen() != null) {
+            boolean show = (getPreferenceScreen().getPreferenceCount()
+                    - (mHeader != null ? 1 : 0)
+                    - (mFooter != null ? 1 : 0)) <= 0;
+            mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE);
+        } else {
+            mEmptyView.setVisibility(View.VISIBLE);
+        }
+    }
+
+    public void setEmptyView(View v) {
+        if (mEmptyView != null) {
+            mEmptyView.setVisibility(View.GONE);
+        }
+        mEmptyView = v;
+        updateEmptyView();
+    }
+
+    public View getEmptyView() {
+        return mEmptyView;
+    }
+
+    /**
+     * Return a valid ListView position or -1 if none is found
+     */
+    private int canUseListViewForHighLighting(String key) {
+        if (getListView() == null) {
+            return -1;
+        }
+
+        RecyclerView listView = getListView();
+        RecyclerView.Adapter adapter = listView.getAdapter();
+
+        if (adapter != null && adapter instanceof PreferenceGroupAdapter) {
+            return findListPositionFromKey((PreferenceGroupAdapter) adapter, key);
+        }
+
+        return -1;
+    }
+
+    @Override
+    public RecyclerView.LayoutManager onCreateLayoutManager() {
+        mLayoutManager = new LinearLayoutManager(getContext());
+        return mLayoutManager;
+    }
+
+    @Override
+    protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
+        mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen);
+        return mAdapter;
+    }
+
+    protected void setAnimationAllowed(boolean animationAllowed) {
+        mAnimationAllowed = animationAllowed;
+    }
+
+    protected void cacheRemoveAllPrefs(PreferenceGroup group) {
+        mPreferenceCache = new ArrayMap<String, Preference>();
+        final int N = group.getPreferenceCount();
+        for (int i = 0; i < N; i++) {
+            Preference p = group.getPreference(i);
+            if (TextUtils.isEmpty(p.getKey())) {
+                continue;
+            }
+            mPreferenceCache.put(p.getKey(), p);
+        }
+    }
+
+    protected Preference getCachedPreference(String key) {
+        return mPreferenceCache != null ? mPreferenceCache.remove(key) : null;
+    }
+
+    protected void removeCachedPrefs(PreferenceGroup group) {
+        for (Preference p : mPreferenceCache.values()) {
+            group.removePreference(p);
+        }
+    }
+
+    protected int getCachedCount() {
+        return mPreferenceCache.size();
+    }
+
+    private void highlightPreference(String key) {
+        final int position = canUseListViewForHighLighting(key);
+        if (position >= 0) {
+            mPreferenceHighlighted = true;
+            mLayoutManager.scrollToPosition(position);
+
+            getView().postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    mAdapter.highlight(position);
+                }
+            }, DELAY_HIGHLIGHT_DURATION_MILLIS);
+        }
+    }
+
+    private int findListPositionFromKey(PreferenceGroupAdapter adapter, String key) {
+        final int count = adapter.getItemCount();
+        for (int n = 0; n < count; n++) {
+            final Preference preference = adapter.getItem(n);
+            final String preferenceKey = preference.getKey();
+            if (preferenceKey != null && preferenceKey.equals(key)) {
+                return n;
+            }
+        }
+        return -1;
+    }
+
     protected void removePreference(String key) {
         Preference pref = findPreference(key);
         if (pref != null) {
@@ -42,6 +454,52 @@
         }
     }
 
+    /*
+     * The name is intentionally made different from Activity#finish(), so that
+     * users won't misunderstand its meaning.
+     */
+    public final void finishFragment() {
+        getActivity().onBackPressed();
+    }
+
+    // Some helpers for functions used by the settings fragments when they were activities
+
+    /**
+     * Returns the ContentResolver from the owning Activity.
+     */
+    protected ContentResolver getContentResolver() {
+        Context context = getActivity();
+        if (context != null) {
+            mContentResolver = context.getContentResolver();
+        }
+        return mContentResolver;
+    }
+
+    /**
+     * Returns the specified system service from the owning Activity.
+     */
+    protected Object getSystemService(final String name) {
+        return getActivity().getSystemService(name);
+    }
+
+    /**
+     * Returns the PackageManager from the owning Activity.
+     */
+    protected PackageManager getPackageManager() {
+        return getActivity().getPackageManager();
+    }
+
+    @Override
+    public void onDetach() {
+        if (isRemoving()) {
+            if (mDialogFragment != null) {
+                mDialogFragment.dismiss();
+                mDialogFragment = null;
+            }
+        }
+        super.onDetach();
+    }
+
     // Dialog management
 
     protected void showDialog(int dialogId) {
@@ -66,6 +524,18 @@
         mDialogFragment = null;
     }
 
+    protected void removeDialog(int dialogId, boolean stateLossAllowed) {
+        if (stateLossAllowed) {
+            if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
+                getFragmentManager().beginTransaction().remove(mDialogFragment).
+                        commitAllowingStateLoss();
+            }
+            mDialogFragment = null;
+        } else {
+            removeDialog(dialogId);
+        }
+    }
+
     /**
      * Sets the OnCancelListener of the dialog shown. This method can only be
      * called after showDialog(int) and before removeDialog(int). The method
@@ -92,6 +562,25 @@
         // override in subclass to attach a dismiss listener, for instance
     }
 
+    @Override
+    public void onDisplayPreferenceDialog(Preference preference) {
+        if (preference.getKey() == null) {
+            // Auto-key preferences that don't have a key, so the dialog can find them.
+            preference.setKey(UUID.randomUUID().toString());
+        }
+        DialogFragment f = null;
+        if (preference instanceof CustomDialogPreference) {
+            f = CustomDialogPreference.CustomPreferenceDialogFragment
+                    .newInstance(preference.getKey());
+        } else {
+            super.onDisplayPreferenceDialog(preference);
+            return;
+        }
+        f.setTargetFragment(this, 0);
+        f.show(getFragmentManager(), "dialog_preference");
+        onDialogShowing();
+    }
+
     public static class SettingsDialogFragment extends DialogFragment {
         private static final String KEY_DIALOG_ID = "key_dialog_id";
         private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id";
@@ -193,5 +682,69 @@
             }
         }
     }
-}
 
+    public void finish() {
+        Activity activity = getActivity();
+        if (activity == null) return;
+        if (getFragmentManager().getBackStackEntryCount() > 0) {
+            getFragmentManager().popBackStack();
+        } else {
+            activity.finish();
+        }
+    }
+
+    protected Intent getIntent() {
+        if (getActivity() == null) {
+            return null;
+        }
+        return getActivity().getIntent();
+    }
+
+    protected void setResult(int result, Intent intent) {
+        if (getActivity() == null) {
+            return;
+        }
+        getActivity().setResult(result, intent);
+    }
+
+    protected void setResult(int result) {
+        if (getActivity() == null) {
+            return;
+        }
+        getActivity().setResult(result);
+    }
+
+    protected final Context getPrefContext() {
+        return getPreferenceManager().getContext();
+    }
+
+    public static class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter {
+
+        private int mHighlightPosition = -1;
+
+        public HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
+            super(preferenceGroup);
+        }
+
+        public void highlight(int position) {
+            mHighlightPosition = position;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder holder, int position) {
+            super.onBindViewHolder(holder, position);
+            if (position == mHighlightPosition) {
+                View v = holder.itemView;
+                if (v.getBackground() != null) {
+                    final int centerX = v.getWidth() / 2;
+                    final int centerY = v.getHeight() / 2;
+                    v.getBackground().setHotspot(centerX, centerY);
+                }
+                v.setPressed(true);
+                v.setPressed(false);
+                mHighlightPosition = -1;
+            }
+        }
+    }
+}
diff --git a/src/org/cyanogenmod/cmparts/SystemSettingSwitchPreference.java b/src/org/cyanogenmod/cmparts/SystemSettingSwitchPreference.java
index 2aefd69..f2111df 100644
--- a/src/org/cyanogenmod/cmparts/SystemSettingSwitchPreference.java
+++ b/src/org/cyanogenmod/cmparts/SystemSettingSwitchPreference.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 import android.provider.Settings;
-import android.preference.SwitchPreference;
+import android.support.v14.preference.SwitchPreference;
 import android.util.AttributeSet;
 
 public class SystemSettingSwitchPreference extends SwitchPreference {
diff --git a/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardManager.java b/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardManager.java
index 1e8b2f3..1031eef 100644
--- a/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardManager.java
+++ b/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardManager.java
@@ -36,7 +36,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Settings;
-import android.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
diff --git a/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardPrefs.java b/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardPrefs.java
index fec619f..0635948 100644
--- a/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardPrefs.java
+++ b/src/org/cyanogenmod/cmparts/privacyguard/PrivacyGuardPrefs.java
@@ -19,10 +19,10 @@
 
 import android.os.Bundle;
 import android.provider.Settings;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.PreferenceFragment;
-import android.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v14.preference.SwitchPreference;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -49,9 +49,7 @@
     }
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         addPreferencesFromResource(R.xml.privacy_guard_prefs);
 
         mPrivacyGuardDefault = (SwitchPreference) findPreference(KEY_PRIVACY_GUARD_DEFAULT);
@@ -66,7 +64,7 @@
     public View onCreateView(LayoutInflater inflater,
             ViewGroup container, Bundle savedInstanceState) {
         final View view = super.onCreateView(inflater, container, savedInstanceState);
-        final ListView list = (ListView) view.findViewById(android.R.id.list);
+        final ViewGroup list = (ViewGroup) getListView().getParent();
         // our container already takes care of the padding
         int paddingTop = list.getPaddingTop();
         int paddingBottom = list.getPaddingBottom();