Fix issue 1967295: Add a method to request reloading of audio settings by AudioService.
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index cfdf5e3..a65a417 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1063,6 +1063,21 @@
         }
     }
 
+    /**
+     *  @hide
+     *  Reload audio settings. This method is called by Settings backup
+     *  agent when audio settings are restored and causes the AudioService
+     *  to read and apply restored settings.
+     */
+    public void reloadAudioSettings() {
+        IAudioService service = getService();
+        try {
+            service.reloadAudioSettings();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in reloadAudioSettings"+e);
+        }
+    }
+
      /**
       * {@hide}
       */
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 937baad..ee41021 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -508,14 +508,14 @@
     /** @see AudioManager#setRingerMode(int) */
     public void setRingerMode(int ringerMode) {
         if (ringerMode != mRingerMode) {
-            setRingerModeInt(ringerMode);
+            setRingerModeInt(ringerMode, true);
 
             // Send sticky broadcast
             broadcastRingerMode();
         }
     }
 
-    private void setRingerModeInt(int ringerMode) {
+    private void setRingerModeInt(int ringerMode, boolean persist) {
         mRingerMode = ringerMode;
 
         // Adjust volumes via posting message
@@ -543,8 +543,10 @@
         }
         
         // Post a persist ringer mode msg
-        sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG,
-                SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
+        if (persist) {
+            sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, SHARED_MSG,
+                    SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
+        }
     }
 
     /** @see AudioManager#shouldVibrate(int) */
@@ -914,6 +916,46 @@
         }
     }
 
+    /** @see AudioManager#reloadAudioSettings() */
+    public void reloadAudioSettings() {
+        // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
+        readPersistedSettings();
+
+        // restore volume settings
+        int numStreamTypes = AudioSystem.getNumStreamTypes();
+        for (int streamType = 0; streamType < numStreamTypes; streamType++) {
+            VolumeStreamState streamState = mStreamStates[streamType];
+
+            // there is no volume setting for STREAM_BLUETOOTH_SCO
+            if (streamType != AudioSystem.STREAM_BLUETOOTH_SCO) {
+                String settingName = System.VOLUME_SETTINGS[streamType];
+                String lastAudibleSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
+
+                streamState.mIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver,
+                        settingName,
+                        AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
+                streamState.mLastAudibleIndex = streamState.getValidIndex(Settings.System.getInt(mContentResolver,
+                        lastAudibleSettingName,
+                        streamState.mIndex > 0 ? streamState.mIndex : AudioManager.DEFAULT_STREAM_VOLUME[streamType]));
+            }
+            // unmute stream that whas muted but is not affect by mute anymore
+            if (streamState.muteCount() != 0 && !isStreamAffectedByMute(streamType)) {
+                int size = streamState.mDeathHandlers.size();
+                for (int i = 0; i < size; i++) {
+                    streamState.mDeathHandlers.get(i).mMuteCount = 1;
+                    streamState.mDeathHandlers.get(i).mute(false);
+                }
+            }
+            // apply stream volume
+            if (streamState.muteCount() == 0) {
+                AudioSystem.setVolume(streamType, streamState.mVolumes[streamState.mIndex]);
+            }
+        }
+
+        // apply new ringer mode
+        setRingerModeInt(getRingerMode(), false);
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Internal methods
     ///////////////////////////////////////////////////////////////////////////
@@ -1426,7 +1468,7 @@
              * Ensure all stream types that should be affected by ringer mode
              * are in the proper state.
              */
-            setRingerModeInt(getRingerMode());
+            setRingerModeInt(getRingerMode(), false);
         }
         
     }
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index f5e242d..9a8264f 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -71,4 +71,5 @@
   
     oneway void unloadSoundEffects();
 
+    oneway void reloadAudioSettings();
 }