Revert volume if it wasn't okayed by user.

During orientation changes or homing, the volume is reverted. Also,
during pause/resume, the original and modified values are remembered and
restored if the dialog was up.
diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java
index db25cfa..46cce52 100644
--- a/core/java/android/preference/VolumePreference.java
+++ b/core/java/android/preference/VolumePreference.java
@@ -16,15 +16,17 @@
 
 package android.preference;
 
+import android.app.Dialog;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
+import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
-import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Handler;
-import android.preference.PreferenceManager;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.provider.Settings;
 import android.provider.Settings.System;
 import android.util.AttributeSet;
@@ -42,7 +44,7 @@
     private static final String TAG = "VolumePreference";
     
     private int mStreamType;
-    
+
     /** May be null if the dialog isn't visible. */
     private SeekBarVolumizer mSeekBarVolumizer;
     
@@ -54,7 +56,7 @@
         mStreamType = a.getInt(android.R.styleable.VolumePreference_streamType, 0);
         a.recycle();        
     }
-    
+
     public void setStreamType(int streamType) {
         mStreamType = streamType;
     }
@@ -65,7 +67,7 @@
     
         final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
         mSeekBarVolumizer = new SeekBarVolumizer(getContext(), seekBar, mStreamType);
-        
+
         getPreferenceManager().registerOnActivityStopListener(this);
 
         // grab focus and key events so that pressing the volume buttons in the
@@ -100,7 +102,7 @@
         if (!positiveResult && mSeekBarVolumizer != null) {
             mSeekBarVolumizer.revertVolume();
         }
-        
+
         cleanup();
     }
 
@@ -113,19 +115,96 @@
      */
     private void cleanup() {
        getPreferenceManager().unregisterOnActivityStopListener(this);
-       
+
        if (mSeekBarVolumizer != null) {
+           Dialog dialog = getDialog();
+           if (dialog != null && dialog.isShowing()) {
+               // Stopped while dialog was showing, revert changes
+               mSeekBarVolumizer.revertVolume();
+           }
            mSeekBarVolumizer.stop();
            mSeekBarVolumizer = null;
        }
+
     }
-   
+
     protected void onSampleStarting(SeekBarVolumizer volumizer) {
         if (mSeekBarVolumizer != null && volumizer != mSeekBarVolumizer) {
             mSeekBarVolumizer.stopSample();
         }
     }
-    
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        final SavedState myState = new SavedState(superState);
+        if (mSeekBarVolumizer != null) {
+            mSeekBarVolumizer.onSaveInstanceState(myState.getVolumeStore());
+        }
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        if (mSeekBarVolumizer != null) {
+            mSeekBarVolumizer.onRestoreInstanceState(myState.getVolumeStore());
+        }
+    }
+
+    public static class VolumeStore {
+        public int volume = -1;
+        public int originalVolume = -1;
+    }
+
+    private static class SavedState extends BaseSavedState {
+        VolumeStore mVolumeStore = new VolumeStore();
+
+        public SavedState(Parcel source) {
+            super(source);
+            mVolumeStore.volume = source.readInt();
+            mVolumeStore.originalVolume = source.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(mVolumeStore.volume);
+            dest.writeInt(mVolumeStore.originalVolume);
+        }
+
+        VolumeStore getVolumeStore() {
+            return mVolumeStore;
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
     /**
      * Turns a {@link SeekBar} into a volume control.
      */
@@ -139,7 +218,7 @@
         private int mOriginalStreamVolume; 
         private Ringtone mRingtone;
     
-        private int mLastProgress;
+        private int mLastProgress = -1;
         private SeekBar mSeekBar;
         
         private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
@@ -153,7 +232,7 @@
                 }
             }
         };
-    
+
         public SeekBarVolumizer(Context context, SeekBar seekBar, int streamType) {
             mContext = context;
             mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -207,7 +286,7 @@
             postSetVolume(progress);
         }
 
-        private void postSetVolume(int progress) {
+        void postSetVolume(int progress) {
             // Do the volume changing separately to give responsive UI
             mLastProgress = progress;
             mHandler.removeCallbacks(this);
@@ -249,5 +328,20 @@
             }
             postSetVolume(mSeekBar.getProgress());
         }
+
+        public void onSaveInstanceState(VolumeStore volumeStore) {
+            if (mLastProgress >= 0) {
+                volumeStore.volume = mLastProgress;
+                volumeStore.originalVolume = mOriginalStreamVolume;
+            }
+        }
+
+        public void onRestoreInstanceState(VolumeStore volumeStore) {
+            if (volumeStore.volume != -1) {
+                mOriginalStreamVolume = volumeStore.originalVolume;
+                mLastProgress = volumeStore.volume;
+                postSetVolume(mLastProgress);
+            }
+        }
     }
 }