auto import from //depot/cupcake/@135843
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
new file mode 100644
index 0000000..a255438
--- /dev/null
+++ b/core/java/android/preference/Preference.java
@@ -0,0 +1,1586 @@
+/*
+ * Copyright (C) 2007 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 android.preference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import com.android.internal.util.CharSequences;
+import android.view.AbsSavedState;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * Represents the basic Preference UI building
+ * block displayed by a {@link PreferenceActivity} in the form of a
+ * {@link ListView}. This class provides the {@link View} to be displayed in
+ * the activity and associates with a {@link SharedPreferences} to
+ * store/retrieve the preference data.
+ * <p>
+ * When specifying a preference hierarchy in XML, each element can point to a
+ * subclass of {@link Preference}, similar to the view hierarchy and layouts.
+ * <p>
+ * This class contains a {@code key} that will be used as the key into the
+ * {@link SharedPreferences}. It is up to the subclass to decide how to store
+ * the value.
+ * 
+ * @attr ref android.R.styleable#Preference_key
+ * @attr ref android.R.styleable#Preference_title
+ * @attr ref android.R.styleable#Preference_summary
+ * @attr ref android.R.styleable#Preference_order
+ * @attr ref android.R.styleable#Preference_layout
+ * @attr ref android.R.styleable#Preference_widgetLayout
+ * @attr ref android.R.styleable#Preference_enabled
+ * @attr ref android.R.styleable#Preference_selectable
+ * @attr ref android.R.styleable#Preference_dependency
+ * @attr ref android.R.styleable#Preference_persistent
+ * @attr ref android.R.styleable#Preference_defaultValue
+ * @attr ref android.R.styleable#Preference_shouldDisableView
+ */
+public class Preference implements Comparable<Preference>, OnDependencyChangeListener { 
+    /**
+     * Specify for {@link #setOrder(int)} if a specific order is not required.
+     */
+    public static final int DEFAULT_ORDER = Integer.MAX_VALUE;
+
+    private Context mContext;
+    private PreferenceManager mPreferenceManager;
+    
+    /**
+     * Set when added to hierarchy since we need a unique ID within that
+     * hierarchy.
+     */
+    private long mId;
+    
+    private OnPreferenceChangeListener mOnChangeListener;
+    private OnPreferenceClickListener mOnClickListener;
+
+    private int mOrder = DEFAULT_ORDER;
+    private CharSequence mTitle;
+    private CharSequence mSummary;
+    private String mKey;
+    private Intent mIntent;
+    private boolean mEnabled = true;
+    private boolean mSelectable = true;
+    private boolean mRequiresKey;
+    private boolean mPersistent = true;
+    private String mDependencyKey;
+    private Object mDefaultValue;
+    
+    /**
+     * @see #setShouldDisableView(boolean)
+     */
+    private boolean mShouldDisableView = true;
+    
+    private int mLayoutResId = com.android.internal.R.layout.preference;
+    private int mWidgetLayoutResId;
+    private boolean mHasSpecifiedLayout = false;
+    
+    private OnPreferenceChangeInternalListener mListener;
+    
+    private List<Preference> mDependents;
+    
+    private boolean mBaseMethodCalled;
+    
+    /**
+     * Interface definition for a callback to be invoked when the value of this
+     * {@link Preference} has been changed by the user and is
+     * about to be set and/or persisted.  This gives the client a chance
+     * to prevent setting and/or persisting the value.
+     */
+    public interface OnPreferenceChangeListener {
+        /**
+         * Called when a Preference has been changed by the user. This is
+         * called before the state of the Preference is about to be updated and
+         * before the state is persisted.
+         * 
+         * @param preference The changed Preference.
+         * @param newValue The new value of the Preference.
+         * @return True to update the state of the Preference with the new value.
+         */
+        boolean onPreferenceChange(Preference preference, Object newValue);
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when a {@link Preference} is
+     * clicked.
+     */
+    public interface OnPreferenceClickListener {
+        /**
+         * Called when a Preference has been clicked.
+         *
+         * @param preference The Preference that was clicked.
+         * @return True if the click was handled.
+         */
+        boolean onPreferenceClick(Preference preference);
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when this
+     * {@link Preference} is changed or, if this is a group, there is an
+     * addition/removal of {@link Preference}(s). This is used internally.
+     */
+    interface OnPreferenceChangeInternalListener {
+        /**
+         * Called when this Preference has changed.
+         * 
+         * @param preference This preference.
+         */
+        void onPreferenceChange(Preference preference);
+        
+        /**
+         * Called when this group has added/removed {@link Preference}(s).
+         * 
+         * @param preference This Preference.
+         */
+        void onPreferenceHierarchyChange(Preference preference);
+    }
+
+    /**
+     * Perform inflation from XML and apply a class-specific base style. This
+     * constructor of Preference allows subclasses to use their own base
+     * style when they are inflating. For example, a {@link CheckBoxPreference}
+     * constructor calls this version of the super class constructor and
+     * supplies {@code android.R.attr.checkBoxPreferenceStyle} for <var>defStyle</var>.
+     * This allows the theme's checkbox preference style to modify all of the base
+     * preference attributes as well as the {@link CheckBoxPreference} class's
+     * attributes.
+     * 
+     * @param context The Context this is associated with, through which it can
+     *            access the current theme, resources, {@link SharedPreferences},
+     *            etc.
+     * @param attrs The attributes of the XML tag that is inflating the preference.
+     * @param defStyle The default style to apply to this preference. If 0, no style
+     *            will be applied (beyond what is included in the theme). This
+     *            may either be an attribute resource, whose value will be
+     *            retrieved from the current theme, or an explicit style
+     *            resource.
+     * @see #Preference(Context, AttributeSet)
+     */
+    public Preference(Context context, AttributeSet attrs, int defStyle) {
+        mContext = context;
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.Preference);
+        if (a.hasValue(com.android.internal.R.styleable.Preference_layout) ||
+                a.hasValue(com.android.internal.R.styleable.Preference_widgetLayout)) {
+            // This preference has a custom layout defined (not one taken from
+            // the default style)
+            mHasSpecifiedLayout = true;
+        }
+        a.recycle();
+        
+        a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Preference,
+                defStyle, 0);
+        for (int i = a.getIndexCount(); i >= 0; i--) {
+            int attr = a.getIndex(i); 
+            switch (attr) {
+                case com.android.internal.R.styleable.Preference_key:
+                    mKey = a.getString(attr);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_title:
+                    mTitle = a.getString(attr);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_summary:
+                    mSummary = a.getString(attr);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_order:
+                    mOrder = a.getInt(attr, mOrder);
+                    break;
+
+                case com.android.internal.R.styleable.Preference_layout:
+                    mLayoutResId = a.getResourceId(attr, mLayoutResId);
+                    break;
+
+                case com.android.internal.R.styleable.Preference_widgetLayout:
+                    mWidgetLayoutResId = a.getResourceId(attr, mWidgetLayoutResId);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_enabled:
+                    mEnabled = a.getBoolean(attr, true);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_selectable:
+                    mSelectable = a.getBoolean(attr, true);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_persistent:
+                    mPersistent = a.getBoolean(attr, mPersistent);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_dependency:
+                    mDependencyKey = a.getString(attr);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_defaultValue:
+                    mDefaultValue = onGetDefaultValue(a, attr);
+                    break;
+                    
+                case com.android.internal.R.styleable.Preference_shouldDisableView:
+                    mShouldDisableView = a.getBoolean(attr, mShouldDisableView);
+                    break;
+            }
+        }
+        a.recycle();
+    }
+    
+    /**
+     * Constructor that is called when inflating a Preference from XML. This is
+     * called when a Preference is being constructed from an XML file, supplying
+     * attributes that were specified in the XML file. This version uses a
+     * default style of 0, so the only attribute values applied are those in the
+     * Context's Theme and the given AttributeSet.
+     * 
+     * @param context The Context this is associated with, through which it can
+     *            access the current theme, resources, {@link SharedPreferences},
+     *            etc.
+     * @param attrs The attributes of the XML tag that is inflating the
+     *            preference.
+     * @see #Preference(Context, AttributeSet, int)
+     */
+    public Preference(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    /**
+     * Constructor to create a Preference.
+     * 
+     * @param context The Context in which to store Preference values.
+     */
+    public Preference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Called when a Preference is being inflated and the default value
+     * attribute needs to be read. Since different Preference types have
+     * different value types, the subclass should get and return the default
+     * value which will be its value type.
+     * <p>
+     * For example, if the value type is String, the body of the method would
+     * proxy to {@link TypedArray#getString(int)}.
+     * 
+     * @param a The set of attributes.
+     * @param index The index of the default value attribute.
+     * @return The default value of this preference type.
+     */
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return null;
+    }
+    
+    /**
+     * Sets an {@link Intent} to be used for
+     * {@link Context#startActivity(Intent)} when this Preference is clicked.
+     * 
+     * @param intent The intent associated with this Preference.
+     */
+    public void setIntent(Intent intent) {
+        mIntent = intent;
+    }
+    
+    /**
+     * Return the {@link Intent} associated with this Preference.
+     * 
+     * @return The {@link Intent} last set via {@link #setIntent(Intent)} or XML. 
+     */
+    public Intent getIntent() {
+        return mIntent;
+    }
+
+    /**
+     * Sets the layout resource that is inflated as the {@link View} to be shown
+     * for this Preference. In most cases, the default layout is sufficient for
+     * custom Preference objects and only the widget layout needs to be changed.
+     * <p>
+     * This layout should contain a {@link ViewGroup} with ID
+     * {@link android.R.id#widget_frame} to be the parent of the specific widget
+     * for this Preference. It should similarly contain
+     * {@link android.R.id#title} and {@link android.R.id#summary}.
+     * 
+     * @param layoutResId The layout resource ID to be inflated and returned as
+     *            a {@link View}.
+     * @see #setWidgetLayoutResource(int)
+     */
+    public void setLayoutResource(int layoutResId) {
+        
+        if (!mHasSpecifiedLayout) {
+            mHasSpecifiedLayout = true;
+        }
+        
+        mLayoutResId = layoutResId;
+    }
+    
+    /**
+     * Gets the layout resource that will be shown as the {@link View} for this Preference.
+     * 
+     * @return The layout resource ID.
+     */
+    public int getLayoutResource() {
+        return mLayoutResId;
+    }
+    
+    /**
+     * Sets The layout for the controllable widget portion of this Preference. This
+     * is inflated into the main layout. For example, a {@link CheckBoxPreference}
+     * would specify a custom layout (consisting of just the CheckBox) here,
+     * instead of creating its own main layout.
+     * 
+     * @param widgetLayoutResId The layout resource ID to be inflated into the
+     *            main layout.
+     * @see #setLayoutResource(int)
+     */
+    public void setWidgetLayoutResource(int widgetLayoutResId) {
+        mWidgetLayoutResId = widgetLayoutResId;
+    }
+
+    /**
+     * Gets the layout resource for the controllable widget portion of this Preference.
+     * 
+     * @return The layout resource ID.
+     */
+    public int getWidgetLayoutResource() {
+        return mWidgetLayoutResId;
+    }
+    
+    /**
+     * Gets the View that will be shown in the {@link PreferenceActivity}.
+     * 
+     * @param convertView The old View to reuse, if possible. Note: You should
+     *            check that this View is non-null and of an appropriate type
+     *            before using. If it is not possible to convert this View to
+     *            display the correct data, this method can create a new View.
+     * @param parent The parent that this View will eventually be attached to.
+     * @return Returns the same Preference object, for chaining multiple calls
+     *         into a single statement.
+     * @see #onCreateView(ViewGroup)
+     * @see #onBindView(View)
+     */
+    public View getView(View convertView, ViewGroup parent) {
+        if (convertView == null) {
+            convertView = onCreateView(parent);
+        }
+        onBindView(convertView);
+        return convertView;
+    }
+    
+    /**
+     * Creates the View to be shown for this Preference in the
+     * {@link PreferenceActivity}. The default behavior is to inflate the main
+     * layout of this Preference (see {@link #setLayoutResource(int)}. If
+     * changing this behavior, please specify a {@link ViewGroup} with ID
+     * {@link android.R.id#widget_frame}.
+     * <p>
+     * Make sure to call through to the superclass's implementation.
+     * 
+     * @param parent The parent that this View will eventually be attached to.
+     * @return The View that displays this Preference.
+     * @see #onBindView(View)
+     */
+    protected View onCreateView(ViewGroup parent) {
+        final LayoutInflater layoutInflater =
+            (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        
+        final View layout = layoutInflater.inflate(mLayoutResId, parent, false); 
+        
+        if (mWidgetLayoutResId != 0) {
+            final ViewGroup widgetFrame = (ViewGroup)layout.findViewById(com.android.internal.R.id.widget_frame);
+            layoutInflater.inflate(mWidgetLayoutResId, widgetFrame);
+        }
+
+        return layout;
+    }
+    
+    /**
+     * Binds the created View to the data for this Preference.
+     * <p>
+     * This is a good place to grab references to custom Views in the layout and
+     * set properties on them.
+     * <p>
+     * Make sure to call through to the superclass's implementation.
+     * 
+     * @param view The View that shows this Preference.
+     * @see #onCreateView(ViewGroup)
+     */
+    protected void onBindView(View view) {
+        TextView textView = (TextView) view.findViewById(com.android.internal.R.id.title); 
+        if (textView != null) {
+            textView.setText(getTitle());
+        }
+        
+        textView = (TextView) view.findViewById(com.android.internal.R.id.summary);
+        if (textView != null) {
+            final CharSequence summary = getSummary();
+            if (!TextUtils.isEmpty(summary)) {
+                if (textView.getVisibility() != View.VISIBLE) {
+                    textView.setVisibility(View.VISIBLE);
+                }
+                
+                textView.setText(getSummary());
+            } else {
+                if (textView.getVisibility() != View.GONE) {
+                    textView.setVisibility(View.GONE);
+                }
+            }
+        }
+        
+        if (mShouldDisableView) {
+            setEnabledStateOnViews(view, isEnabled());
+        }
+    }
+    
+    /**
+     * Makes sure the view (and any children) get the enabled state changed.
+     */
+    private void setEnabledStateOnViews(View v, boolean enabled) {
+        v.setEnabled(enabled);
+        
+        if (v instanceof ViewGroup) {
+            final ViewGroup vg = (ViewGroup) v;
+            for (int i = vg.getChildCount() - 1; i >= 0; i--) {
+                setEnabledStateOnViews(vg.getChildAt(i), enabled);
+            }
+        }
+    }
+    
+    /**
+     * Sets the order of this Preference with respect to other
+     * Preference objects on the same level. If this is not specified, the
+     * default behavior is to sort alphabetically. The
+     * {@link PreferenceGroup#setOrderingAsAdded(boolean)} can be used to order
+     * Preference objects based on the order they appear in the XML.
+     * 
+     * @param order The order for this Preference. A lower value will be shown
+     *            first. Use {@link #DEFAULT_ORDER} to sort alphabetically or
+     *            allow ordering from XML.
+     * @see PreferenceGroup#setOrderingAsAdded(boolean)
+     * @see #DEFAULT_ORDER
+     */
+    public void setOrder(int order) {
+        if (order != mOrder) {
+            mOrder = order;
+
+            // Reorder the list 
+            notifyHierarchyChanged();
+        }
+    }
+    
+    /**
+     * Gets the order of this Preference with respect to other Preference objects
+     * on the same level.
+     * 
+     * @return The order of this Preference.
+     * @see #setOrder(int)
+     */
+    public int getOrder() {
+        return mOrder;
+    }
+
+    /**
+     * Sets the title for this Preference with a CharSequence. 
+     * This title will be placed into the ID
+     * {@link android.R.id#title} within the View created by
+     * {@link #onCreateView(ViewGroup)}.
+     * 
+     * @param title The title for this Preference.
+     */
+    public void setTitle(CharSequence title) {
+        if (title == null && mTitle != null || title != null && !title.equals(mTitle)) {
+            mTitle = title;
+            notifyChanged();
+        }
+    }
+    
+    /**
+     * Sets the title for this Preference with a resource ID. 
+     * 
+     * @see #setTitle(CharSequence)
+     * @param titleResId The title as a resource ID.
+     */
+    public void setTitle(int titleResId) {
+        setTitle(mContext.getString(titleResId));
+    }
+    
+    /**
+     * Returns the title of this Preference.
+     * 
+     * @return The title.
+     * @see #setTitle(CharSequence)
+     */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns the summary of this Preference.
+     * 
+     * @return The summary.
+     * @see #setSummary(CharSequence)
+     */
+    public CharSequence getSummary() {
+        return mSummary;
+    }
+
+    /**
+     * Sets the summary for this Preference with a CharSequence. 
+     * 
+     * @param summary The summary for the preference.
+     */
+    public void setSummary(CharSequence summary) {
+        if (summary == null && mSummary != null || summary != null && !summary.equals(mSummary)) {
+            mSummary = summary;
+            notifyChanged();
+        }
+    }
+
+    /**
+     * Sets the summary for this Preference with a resource ID. 
+     * 
+     * @see #setSummary(CharSequence)
+     * @param summaryResId The summary as a resource.
+     */
+    public void setSummary(int summaryResId) {
+        setSummary(mContext.getString(summaryResId));
+    }
+    
+    /**
+     * Sets whether this Preference is enabled. If disabled, it will
+     * not handle clicks.
+     * 
+     * @param enabled Set true to enable it.
+     */
+    public void setEnabled(boolean enabled) {
+        if (mEnabled != enabled) {
+            mEnabled = enabled;
+
+            // Enabled state can change dependent preferences' states, so notify
+            notifyDependencyChange(shouldDisableDependents());
+
+            notifyChanged();
+        }
+    }
+    
+    /**
+     * Checks whether this Preference should be enabled in the list.
+     * 
+     * @return True if this Preference is enabled, false otherwise.
+     */
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Sets whether this Preference is selectable.
+     * 
+     * @param selectable Set true to make it selectable.
+     */
+    public void setSelectable(boolean selectable) {
+        if (mSelectable != selectable) {
+            mSelectable = selectable;
+            notifyChanged();
+        }
+    }
+    
+    /**
+     * Checks whether this Preference should be selectable in the list.
+     * 
+     * @return True if it is selectable, false otherwise.
+     */
+    public boolean isSelectable() {
+        return mSelectable;
+    }
+
+    /**
+     * Sets whether this Preference should disable its view when it gets
+     * disabled.
+     * <p>
+     * For example, set this and {@link #setEnabled(boolean)} to false for
+     * preferences that are only displaying information and 1) should not be
+     * clickable 2) should not have the view set to the disabled state.
+     * 
+     * @param shouldDisableView Set true if this preference should disable its view
+     *            when the preference is disabled.
+     */
+    public void setShouldDisableView(boolean shouldDisableView) {
+        mShouldDisableView = shouldDisableView;
+        notifyChanged();
+    }
+    
+    /**
+     * Checks whether this Preference should disable its view when it's action is disabled.
+     * @see #setShouldDisableView(boolean)
+     * @return True if it should disable the view. 
+     */
+    public boolean getShouldDisableView() {
+        return mShouldDisableView;
+    }
+
+    /**
+     * Returns a unique ID for this Preference.  This ID should be unique across all
+     * Preference objects in a hierarchy.
+     * 
+     * @return A unique ID for this Preference.
+     */
+    long getId() {
+        return mId;
+    }
+    
+    /**
+     * Processes a click on the preference. This includes saving the value to
+     * the {@link SharedPreferences}. However, the overridden method should
+     * call {@link #callChangeListener(Object)} to make sure the client wants to
+     * update the preference's state with the new value.
+     */
+    protected void onClick() {
+    }
+    
+    /**
+     * Sets the key for this Preference, which is used as a key to the
+     * {@link SharedPreferences}. This should be unique for the package.
+     * 
+     * @param key The key for the preference.
+     */
+    public void setKey(String key) {
+        mKey = key;
+        
+        if (mRequiresKey && !hasKey()) {
+            requireKey();
+        }
+    }
+    
+    /**
+     * Gets the key for this Preference, which is also the key used for storing
+     * values into SharedPreferences.
+     * 
+     * @return The key.
+     */
+    public String getKey() {
+        return mKey;
+    }
+    
+    /**
+     * Checks whether the key is present, and if it isn't throws an
+     * exception. This should be called by subclasses that store preferences in
+     * the {@link SharedPreferences}.
+     * 
+     * @throws IllegalStateException If there is no key assigned.
+     */
+    void requireKey() {
+        if (mKey == null) {
+            throw new IllegalStateException("Preference does not have a key assigned.");
+        }
+        
+        mRequiresKey = true;
+    }
+    
+    /**
+     * Checks whether this Preference has a valid key.
+     * 
+     * @return True if the key exists and is not a blank string, false otherwise.
+     */
+    public boolean hasKey() {
+        return !TextUtils.isEmpty(mKey);
+    }
+    
+    /**
+     * Checks whether this Preference is persistent. If it is, it stores its value(s) into
+     * the persistent {@link SharedPreferences} storage.
+     * 
+     * @return True if it is persistent.
+     */
+    public boolean isPersistent() {
+        return mPersistent;
+    }
+    
+    /**
+     * Checks whether, at the given time this method is called,
+     * this Preference should store/restore its value(s) into the
+     * {@link SharedPreferences}. This, at minimum, checks whether this
+     * Preference is persistent and it currently has a key. Before you
+     * save/restore from the {@link SharedPreferences}, check this first.
+     * 
+     * @return True if it should persist the value.
+     */
+    protected boolean shouldPersist() {
+        return mPreferenceManager != null && isPersistent() && hasKey();
+    }
+    
+    /**
+     * Sets whether this Preference is persistent. When persistent,
+     * it stores its value(s) into the persistent {@link SharedPreferences}
+     * storage.
+     * 
+     * @param persistent Set true if it should store its value(s) into the {@link SharedPreferences}.
+     */
+    public void setPersistent(boolean persistent) {
+        mPersistent = persistent;
+    }
+    
+    /**
+     * Call this method after the user changes the preference, but before the
+     * internal state is set. This allows the client to ignore the user value.
+     * 
+     * @param newValue The new value of this Preference.
+     * @return True if the user value should be set as the preference
+     *         value (and persisted).
+     */
+    protected boolean callChangeListener(Object newValue) {
+        return mOnChangeListener == null ? true : mOnChangeListener.onPreferenceChange(this, newValue);
+    }
+    
+    /**
+     * Sets the callback to be invoked when this Preference is changed by the
+     * user (but before the internal state has been updated).
+     * 
+     * @param onPreferenceChangeListener The callback to be invoked.
+     */
+    public void setOnPreferenceChangeListener(OnPreferenceChangeListener onPreferenceChangeListener) {
+        mOnChangeListener = onPreferenceChangeListener;
+    }
+
+    /**
+     * Returns the callback to be invoked when this Preference is changed by the
+     * user (but before the internal state has been updated).
+     * 
+     * @return The callback to be invoked.
+     */
+    public OnPreferenceChangeListener getOnPreferenceChangeListener() {
+        return mOnChangeListener;
+    }
+
+    /**
+     * Sets the callback to be invoked when this Preference is clicked.
+     * 
+     * @param onPreferenceClickListener The callback to be invoked.
+     */
+    public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
+        mOnClickListener = onPreferenceClickListener;
+    }
+
+    /**
+     * Returns the callback to be invoked when this Preference is clicked.
+     * 
+     * @return The callback to be invoked.
+     */
+    public OnPreferenceClickListener getOnPreferenceClickListener() {
+        return mOnClickListener;
+    }
+
+    /**
+     * Called when a click should be performed.
+     * 
+     * @param preferenceScreen A {@link PreferenceScreen} whose hierarchy click
+     *            listener should be called in the proper order (between other
+     *            processing). May be null.
+     */
+    void performClick(PreferenceScreen preferenceScreen) {
+        
+        if (!isEnabled()) {
+            return;
+        }
+        
+        onClick();
+        
+        if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) {
+            return;
+        }
+        
+        PreferenceManager preferenceManager = getPreferenceManager();
+        if (preferenceManager != null) {
+            PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager
+                    .getOnPreferenceTreeClickListener();
+            if (preferenceScreen != null && listener != null
+                    && listener.onPreferenceTreeClick(preferenceScreen, this)) {
+                return;
+            }
+        }
+        
+        if (mIntent != null) {
+            Context context = getContext();
+            context.startActivity(mIntent);
+        }
+    }
+    
+    /**
+     * Returns the {@link android.content.Context} of this Preference. 
+     * Each Preference in a Preference hierarchy can be
+     * from different Context (for example, if multiple activities provide preferences into a single
+     * {@link PreferenceActivity}). This Context will be used to save the Preference values.
+     * 
+     * @return The Context of this Preference.
+     */
+    public Context getContext() {
+        return mContext;
+    }
+    
+    /**
+     * Returns the {@link SharedPreferences} where this Preference can read its
+     * value(s). Usually, it's easier to use one of the helper read methods:
+     * {@link #getPersistedBoolean(boolean)}, {@link #getPersistedFloat(float)},
+     * {@link #getPersistedInt(int)}, {@link #getPersistedLong(long)},
+     * {@link #getPersistedString(String)}. To save values, see
+     * {@link #getEditor()}.
+     * <p>
+     * In some cases, writes to the {@link #getEditor()} will not be committed
+     * right away and hence not show up in the returned
+     * {@link SharedPreferences}, this is intended behavior to improve
+     * performance.
+     * 
+     * @return The {@link SharedPreferences} where this Preference reads its
+     *         value(s), or null if it isn't attached to a Preference hierarchy.
+     * @see #getEditor()
+     */
+    public SharedPreferences getSharedPreferences() {
+        if (mPreferenceManager == null) {
+            return null;
+        }
+        
+        return mPreferenceManager.getSharedPreferences();
+    }
+    
+    /**
+     * Returns an {@link SharedPreferences.Editor} where this Preference can
+     * save its value(s). Usually it's easier to use one of the helper save
+     * methods: {@link #persistBoolean(boolean)}, {@link #persistFloat(float)},
+     * {@link #persistInt(int)}, {@link #persistLong(long)},
+     * {@link #persistString(String)}. To read values, see
+     * {@link #getSharedPreferences()}. If {@link #shouldCommit()} returns
+     * true, it is this Preference's responsibility to commit.
+     * <p>
+     * In some cases, writes to this will not be committed right away and hence
+     * not show up in the SharedPreferences, this is intended behavior to
+     * improve performance.
+     * 
+     * @return A {@link SharedPreferences.Editor} where this preference saves
+     *         its value(s), or null if it isn't attached to a Preference
+     *         hierarchy.
+     * @see #shouldCommit()
+     * @see #getSharedPreferences()
+     */
+    public SharedPreferences.Editor getEditor() {
+        if (mPreferenceManager == null) {
+            return null;
+        }
+        
+        return mPreferenceManager.getEditor();
+    }
+    
+    /**
+     * Returns whether the {@link Preference} should commit its saved value(s) in
+     * {@link #getEditor()}. This may return false in situations where batch
+     * committing is being done (by the manager) to improve performance.
+     * 
+     * @return Whether the Preference should commit its saved value(s).
+     * @see #getEditor()
+     */
+    public boolean shouldCommit() {
+        if (mPreferenceManager == null) {
+            return false;
+        }
+        
+        return mPreferenceManager.shouldCommit();
+    }
+    
+    /**
+     * Compares Preference objects based on order (if set), otherwise alphabetically on the titles.
+     * 
+     * @param another The Preference to compare to this one.
+     * @return 0 if the same; less than 0 if this Preference sorts ahead of <var>another</var>;
+     *          greater than 0 if this Preference sorts after <var>another</var>.
+     */
+    public int compareTo(Preference another) {
+        if (mOrder != DEFAULT_ORDER
+                || (mOrder == DEFAULT_ORDER && another.mOrder != DEFAULT_ORDER)) {
+            // Do order comparison
+            return mOrder - another.mOrder; 
+        } else if (mTitle == null) {
+            return 1;
+        } else if (another.mTitle == null) {
+            return -1;
+        } else {
+            // Do name comparison
+            return CharSequences.compareToIgnoreCase(mTitle, another.mTitle);
+        }
+    }
+    
+    /**
+     * Sets the internal change listener.
+     * 
+     * @param listener The listener.
+     * @see #notifyChanged()
+     */
+    final void setOnPreferenceChangeInternalListener(OnPreferenceChangeInternalListener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Should be called when the data of this {@link Preference} has changed.
+     */
+    protected void notifyChanged() {
+        if (mListener != null) {
+            mListener.onPreferenceChange(this);
+        }
+    }
+    
+    /**
+     * Should be called when a Preference has been
+     * added/removed from this group, or the ordering should be
+     * re-evaluated.
+     */
+    protected void notifyHierarchyChanged() {
+        if (mListener != null) {
+            mListener.onPreferenceHierarchyChange(this);
+        }
+    }
+
+    /**
+     * Gets the {@link PreferenceManager} that manages this Preference object's tree.
+     * 
+     * @return The {@link PreferenceManager}.
+     */
+    public PreferenceManager getPreferenceManager() {
+        return mPreferenceManager;
+    }
+    
+    /**
+     * Called when this Preference has been attached to a Preference hierarchy.
+     * Make sure to call the super implementation.
+     * 
+     * @param preferenceManager The PreferenceManager of the hierarchy.
+     */
+    protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+        mPreferenceManager = preferenceManager;
+        
+        mId = preferenceManager.getNextId();
+        
+        dispatchSetInitialValue();
+    }
+    
+    /**
+     * Called when the Preference hierarchy has been attached to the
+     * {@link PreferenceActivity}. This can also be called when this
+     * Preference has been attached to a group that was already attached
+     * to the {@link PreferenceActivity}.
+     */
+    protected void onAttachedToActivity() {
+        // At this point, the hierarchy that this preference is in is connected
+        // with all other preferences.
+        registerDependency();
+    }
+
+    private void registerDependency() {
+        
+        if (TextUtils.isEmpty(mDependencyKey)) return;
+        
+        Preference preference = findPreferenceInHierarchy(mDependencyKey);
+        if (preference != null) {
+            preference.registerDependent(this);
+        } else {
+            throw new IllegalStateException("Dependency \"" + mDependencyKey
+                    + "\" not found for preference \"" + mKey + "\" (title: \"" + mTitle + "\"");
+        }
+    }
+
+    private void unregisterDependency() {
+        if (mDependencyKey != null) {
+            final Preference oldDependency = findPreferenceInHierarchy(mDependencyKey);
+            if (oldDependency != null) {
+                oldDependency.unregisterDependent(this);
+            }
+        }
+    }
+    
+    /**
+     * Finds a Preference in this hierarchy (the whole thing,
+     * even above/below your {@link PreferenceScreen} screen break) with the given
+     * key.
+     * <p>
+     * This only functions after we have been attached to a hierarchy.
+     * 
+     * @param key The key of the Preference to find.
+     * @return The Preference that uses the given key.
+     */
+    protected Preference findPreferenceInHierarchy(String key) {
+        if (TextUtils.isEmpty(key) || mPreferenceManager == null) {
+            return null;
+        }
+        
+        return mPreferenceManager.findPreference(key);
+    }
+    
+    /**
+     * Adds a dependent Preference on this Preference so we can notify it.
+     * Usually, the dependent Preference registers itself (it's good for it to
+     * know it depends on something), so please use
+     * {@link Preference#setDependency(String)} on the dependent Preference.
+     * 
+     * @param dependent The dependent Preference that will be enabled/disabled
+     *            according to the state of this Preference.
+     */
+    private void registerDependent(Preference dependent) {
+        if (mDependents == null) {
+            mDependents = new ArrayList<Preference>();
+        }
+        
+        mDependents.add(dependent);
+        
+        dependent.onDependencyChanged(this, shouldDisableDependents());
+    }
+    
+    /**
+     * Removes a dependent Preference on this Preference.
+     * 
+     * @param dependent The dependent Preference that will be enabled/disabled
+     *            according to the state of this Preference.
+     * @return Returns the same Preference object, for chaining multiple calls
+     *         into a single statement.
+     */
+    private void unregisterDependent(Preference dependent) {
+        if (mDependents != null) {
+            mDependents.remove(dependent);
+        }
+    }
+    
+    /**
+     * Notifies any listening dependents of a change that affects the
+     * dependency.
+     * 
+     * @param disableDependents Whether this Preference should disable
+     *            its dependents.
+     */
+    public void notifyDependencyChange(boolean disableDependents) {
+        final List<Preference> dependents = mDependents;
+        
+        if (dependents == null) {
+            return;
+        }
+        
+        final int dependentsCount = dependents.size();
+        for (int i = 0; i < dependentsCount; i++) {
+            dependents.get(i).onDependencyChanged(this, disableDependents);
+        }
+    }
+
+    /**
+     * Called when the dependency changes.
+     * 
+     * @param dependency The Preference that this Preference depends on.
+     * @param disableDependent Set true to disable this Preference.
+     */
+    public void onDependencyChanged(Preference dependency, boolean disableDependent) {
+        setEnabled(!disableDependent);
+    }
+    
+    /**
+     * Checks whether this preference's dependents should currently be
+     * disabled.
+     * 
+     * @return True if the dependents should be disabled, otherwise false.
+     */
+    public boolean shouldDisableDependents() {
+        return !isEnabled();
+    }
+    
+    /**
+     * Sets the key of a Preference that this Preference will depend on. If that
+     * Preference is not set or is off, this Preference will be disabled.
+     * 
+     * @param dependencyKey The key of the Preference that this depends on.
+     */
+    public void setDependency(String dependencyKey) {
+        // Unregister the old dependency, if we had one
+        unregisterDependency();
+        
+        // Register the new
+        mDependencyKey = dependencyKey;
+        registerDependency();
+    }
+    
+    /**
+     * Returns the key of the dependency on this Preference.
+     * 
+     * @return The key of the dependency.
+     * @see #setDependency(String)
+     */
+    public String getDependency() {
+        return mDependencyKey;
+    }
+    
+    /**
+     * Called when this Preference is being removed from the hierarchy. You
+     * should remove any references to this Preference that you know about. Make
+     * sure to call through to the superclass implementation.
+     */
+    protected void onPrepareForRemoval() {
+        unregisterDependency();
+    }
+    
+    /**
+     * Sets the default value for this Preference, which will be set either if
+     * persistence is off or persistence is on and the preference is not found
+     * in the persistent storage.
+     * 
+     * @param defaultValue The default value.
+     */
+    public void setDefaultValue(Object defaultValue) {
+        mDefaultValue = defaultValue;
+    }
+    
+    private void dispatchSetInitialValue() {
+        // By now, we know if we are persistent.
+        final boolean shouldPersist = shouldPersist();
+        if (!shouldPersist || !getSharedPreferences().contains(mKey)) {
+            if (mDefaultValue != null) {
+                onSetInitialValue(false, mDefaultValue);
+            }
+        } else {
+            onSetInitialValue(true, null);
+        }
+    }
+    
+    /**
+     * Implement this to set the initial value of the Preference. 
+     * <p>
+     * If <var>restorePersistedValue</var> is true, you should restore the 
+     * Preference value from the {@link android.content.SharedPreferences}. If 
+     * <var>restorePersistedValue</var> is false, you should set the Preference 
+     * value to defaultValue that is given (and possibly store to SharedPreferences 
+     * if {@link #shouldPersist()} is true).
+     * <p>
+     * This may not always be called. One example is if it should not persist
+     * but there is no default value given.
+     * 
+     * @param restorePersistedValue True to restore the persisted value;
+     *            false to use the given <var>defaultValue</var>.
+     * @param defaultValue The default value for this Preference. Only use this
+     *            if <var>restorePersistedValue</var> is false.
+     */
+    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
+    }
+
+    private void tryCommit(SharedPreferences.Editor editor) {
+        if (mPreferenceManager.shouldCommit()) {
+            editor.commit();
+        }
+    }
+    
+    /**
+     * Attempts to persist a String to the {@link android.content.SharedPreferences}.
+     * <p>
+     * This will check if this Preference is persistent, get an editor from
+     * the {@link PreferenceManager}, put in the string, and check if we should commit (and
+     * commit if so).
+     * 
+     * @param value The value to persist.
+     * @return True if the Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #getPersistedString(String)
+     */
+    protected boolean persistString(String value) {
+        if (shouldPersist()) {
+            // Shouldn't store null
+            if (value == getPersistedString(null)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+            
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putString(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Attempts to get a persisted String from the {@link android.content.SharedPreferences}.
+     * <p>
+     * This will check if this Preference is persistent, get the SharedPreferences
+     * from the {@link PreferenceManager}, and get the value.
+     * 
+     * @param defaultReturnValue The default value to return if either the
+     *            Preference is not persistent or the Preference is not in the
+     *            shared preferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #persistString(String)
+     */
+    protected String getPersistedString(String defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+        
+        return mPreferenceManager.getSharedPreferences().getString(mKey, defaultReturnValue);
+    }
+    
+    /**
+     * Attempts to persist an int to the {@link android.content.SharedPreferences}.
+     * 
+     * @param value The value to persist.
+     * @return True if the Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedInt(int)
+     */
+    protected boolean persistInt(int value) {
+        if (shouldPersist()) {
+            if (value == getPersistedInt(~value)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+            
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putInt(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Attempts to get a persisted int from the {@link android.content.SharedPreferences}.
+     * 
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistInt(int)
+     */
+    protected int getPersistedInt(int defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+        
+        return mPreferenceManager.getSharedPreferences().getInt(mKey, defaultReturnValue);
+    }
+    
+    /**
+     * Attempts to persist a float to the {@link android.content.SharedPreferences}.
+     * 
+     * @param value The value to persist.
+     * @return True if this Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedFloat(float)
+     */
+    protected boolean persistFloat(float value) {
+        if (shouldPersist()) {
+            if (value == getPersistedFloat(Float.NaN)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putFloat(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Attempts to get a persisted float from the {@link android.content.SharedPreferences}.
+     * 
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistFloat(float)
+     */
+    protected float getPersistedFloat(float defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+        
+        return mPreferenceManager.getSharedPreferences().getFloat(mKey, defaultReturnValue);
+    }
+    
+    /**
+     * Attempts to persist a long to the {@link android.content.SharedPreferences}.
+     * 
+     * @param value The value to persist.
+     * @return True if this Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedLong(long)
+     */
+    protected boolean persistLong(long value) {
+        if (shouldPersist()) {
+            if (value == getPersistedLong(~value)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+            
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putLong(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Attempts to get a persisted long from the {@link android.content.SharedPreferences}.
+     * 
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistLong(long)
+     */
+    protected long getPersistedLong(long defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+        
+        return mPreferenceManager.getSharedPreferences().getLong(mKey, defaultReturnValue);
+    }
+    
+    /**
+     * Attempts to persist a boolean to the {@link android.content.SharedPreferences}.
+     * 
+     * @param value The value to persist.
+     * @return True if this Preference is persistent. (This is not whether the
+     *         value was persisted, since we may not necessarily commit if there
+     *         will be a batch commit later.)
+     * @see #persistString(String)
+     * @see #getPersistedBoolean(boolean)
+     */
+    protected boolean persistBoolean(boolean value) {
+        if (shouldPersist()) {
+            if (value == getPersistedBoolean(!value)) {
+                // It's already there, so the same as persisting
+                return true;
+            }
+            
+            SharedPreferences.Editor editor = mPreferenceManager.getEditor();
+            editor.putBoolean(mKey, value);
+            tryCommit(editor);
+            return true;
+        }
+        return false;
+    }
+    
+    /**
+     * Attempts to get a persisted boolean from the {@link android.content.SharedPreferences}.
+     * 
+     * @param defaultReturnValue The default value to return if either this
+     *            Preference is not persistent or this Preference is not in the
+     *            SharedPreferences.
+     * @return The value from the SharedPreferences or the default return
+     *         value.
+     * @see #getPersistedString(String)
+     * @see #persistBoolean(boolean)
+     */
+    protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+        if (!shouldPersist()) {
+            return defaultReturnValue;
+        }
+        
+        return mPreferenceManager.getSharedPreferences().getBoolean(mKey, defaultReturnValue);
+    }
+    
+    boolean hasSpecifiedLayout() {
+        return mHasSpecifiedLayout;
+    }
+    
+    @Override
+    public String toString() {
+        return getFilterableStringBuilder().toString();
+    }
+        
+    /**
+     * Returns the text that will be used to filter this Preference depending on
+     * user input.
+     * <p>
+     * If overridding and calling through to the superclass, make sure to prepend
+     * your additions with a space.
+     * 
+     * @return Text as a {@link StringBuilder} that will be used to filter this
+     *         preference. By default, this is the title and summary
+     *         (concatenated with a space).
+     */
+    StringBuilder getFilterableStringBuilder() {
+        StringBuilder sb = new StringBuilder();
+        CharSequence title = getTitle();
+        if (!TextUtils.isEmpty(title)) {
+            sb.append(title).append(' ');
+        }
+        CharSequence summary = getSummary();
+        if (!TextUtils.isEmpty(summary)) {
+            sb.append(summary).append(' ');
+        }
+        // Drop the last space
+        sb.setLength(sb.length() - 1);
+        return sb;
+    }
+
+    /**
+     * Store this Preference hierarchy's frozen state into the given container.
+     * 
+     * @param container The Bundle in which to save the instance of this Preference.
+     * 
+     * @see #restoreHierarchyState
+     * @see #onSaveInstanceState
+     */
+    public void saveHierarchyState(Bundle container) {
+        dispatchSaveInstanceState(container);
+    }
+
+    /**
+     * Called by {@link #saveHierarchyState} to store the instance for this Preference and its children.
+     * May be overridden to modify how the save happens for children. For example, some
+     * Preference objects may want to not store an instance for their children.
+     * 
+     * @param container The Bundle in which to save the instance of this Preference.
+     * 
+     * @see #saveHierarchyState
+     * @see #onSaveInstanceState
+     */
+    void dispatchSaveInstanceState(Bundle container) {
+        if (hasKey()) {
+            mBaseMethodCalled = false;
+            Parcelable state = onSaveInstanceState();
+            if (!mBaseMethodCalled) {
+                throw new IllegalStateException(
+                        "Derived class did not call super.onSaveInstanceState()");
+            }
+            if (state != null) {
+                container.putParcelable(mKey, state);
+            }
+        }
+    }
+
+    /**
+     * Hook allowing a Preference to generate a representation of its internal
+     * state that can later be used to create a new instance with that same
+     * state. This state should only contain information that is not persistent
+     * or can be reconstructed later.
+     * 
+     * @return A Parcelable object containing the current dynamic state of
+     *         this Preference, or null if there is nothing interesting to save.
+     *         The default implementation returns null.
+     * @see #onRestoreInstanceState
+     * @see #saveHierarchyState
+     */
+    protected Parcelable onSaveInstanceState() {
+        mBaseMethodCalled = true;
+        return BaseSavedState.EMPTY_STATE;
+    }
+
+    /**
+     * Restore this Preference hierarchy's previously saved state from the given container.
+     * 
+     * @param container The Bundle that holds the previously saved state.
+     * 
+     * @see #saveHierarchyState
+     * @see #onRestoreInstanceState
+     */
+    public void restoreHierarchyState(Bundle container) {
+        dispatchRestoreInstanceState(container);
+    }
+
+    /**
+     * Called by {@link #restoreHierarchyState} to retrieve the saved state for this
+     * Preference and its children. May be overridden to modify how restoring
+     * happens to the children of a Preference. For example, some Preference objects may
+     * not want to save state for their children.
+     * 
+     * @param container The Bundle that holds the previously saved state.
+     * @see #restoreHierarchyState
+     * @see #onRestoreInstanceState
+     */
+    void dispatchRestoreInstanceState(Bundle container) {
+        if (hasKey()) {
+            Parcelable state = container.getParcelable(mKey);
+            if (state != null) {
+                mBaseMethodCalled = false;
+                onRestoreInstanceState(state);
+                if (!mBaseMethodCalled) {
+                    throw new IllegalStateException(
+                            "Derived class did not call super.onRestoreInstanceState()");
+                }
+            }
+        }
+    }
+
+    /**
+     * Hook allowing a Preference to re-apply a representation of its internal
+     * state that had previously been generated by {@link #onSaveInstanceState}.
+     * This function will never be called with a null state.
+     * 
+     * @param state The saved state that had previously been returned by
+     *            {@link #onSaveInstanceState}.
+     * @see #onSaveInstanceState
+     * @see #restoreHierarchyState
+     */
+    protected void onRestoreInstanceState(Parcelable state) {
+        mBaseMethodCalled = true;
+        if (state != BaseSavedState.EMPTY_STATE && state != null) {
+            throw new IllegalArgumentException("Wrong state class -- expecting Preference State");
+        }
+    }
+
+    /**
+     * A base class for managing the instance state of a {@link Preference}.
+     */
+    public static class BaseSavedState extends AbsSavedState {
+        public BaseSavedState(Parcel source) {
+            super(source);
+        }
+
+        public BaseSavedState(Parcelable superState) {
+            super(superState);
+        }
+        
+        public static final Parcelable.Creator<BaseSavedState> CREATOR =
+                new Parcelable.Creator<BaseSavedState>() {
+            public BaseSavedState createFromParcel(Parcel in) {
+                return new BaseSavedState(in);
+            }
+
+            public BaseSavedState[] newArray(int size) {
+                return new BaseSavedState[size];
+            }
+        };
+    }
+
+}