Fix issue #899198 MODE_RINGER_STREAMS_AFFECTED does not restore volumes correctly
The problem is that setRingerModeInt() does not handle streams not affected by ringer mode: when enabling "Alarm in silent mode" while in silent mode, setRingerModeInt is called after alarm streamis removed from ringer mode affected streams, and nothing is done.
The fix constists in also processing streams that are not affected by ringer mode and to restore last audible volume for them. It does not arm reapplying the volume for streams the are never affected by ringer mode as we don't do this very often.
The other problem noted in the bug report (ringer volume always restored to non zero value when exiting silent mode even if set to zero before) is also fixed: a new parameter is added to setIndex() and setStreamVolumeInt() to explicitely request to store the volume index as last audible instead of doing it automatically if index > 0.
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 881de4d..da15adf 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -163,6 +163,9 @@
*/
private int mRingerMode;
+ /** @see System#MODE_RINGER_STREAMS_AFFECTED */
+ private int mRingerModeAffectedStreams;
+
/** @see System#MUTE_STREAMS_AFFECTED */
private int mMuteAffectedStreams;
@@ -286,6 +289,10 @@
mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0);
+ mRingerModeAffectedStreams = Settings.System.getInt(cr,
+ Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ ((1 << AudioManager.STREAM_RING)|(1 << AudioManager.STREAM_NOTIFICATION)|(1 << AudioManager.STREAM_SYSTEM)));
+
mMuteAffectedStreams = System.getInt(cr,
System.MUTE_STREAMS_AFFECTED,
((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
@@ -399,7 +406,7 @@
ensureValidStreamType(streamType);
syncRingerAndNotificationStreamVolume(streamType, index, false);
- setStreamVolumeInt(streamType, index, false);
+ setStreamVolumeInt(streamType, index, false, true);
// UI, etc.
mVolumePanel.postVolumeChanged(streamType, flags);
@@ -437,7 +444,7 @@
}
if (streamType == AudioManager.STREAM_RING) {
// One-off to sync notification volume to ringer volume
- setStreamVolumeInt(AudioManager.STREAM_NOTIFICATION, index, force);
+ setStreamVolumeInt(AudioManager.STREAM_NOTIFICATION, index, force, true);
}
}
}
@@ -451,10 +458,11 @@
* @param index Desired volume index of the stream
* @param force If true, set the volume even if the desired volume is same
* as the current volume.
+ * @param lastAudible If true, stores new index as last audible one
*/
- private void setStreamVolumeInt(int streamType, int index, boolean force) {
+ private void setStreamVolumeInt(int streamType, int index, boolean force, boolean lastAudible) {
VolumeStreamState streamState = mStreamStates[streamType];
- if (streamState.setIndex(index) || force) {
+ if (streamState.setIndex(index, lastAudible) || force) {
// Post message to set system volume (it in turn will post a message
// to persist). Do not change volume if stream is muted.
if (streamState.muteCount() == 0) {
@@ -517,13 +525,20 @@
if (!isStreamAffectedByRingerMode(streamType)) continue;
// Bring back last audible volume
setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex,
- false);
+ false, false);
}
} else {
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
- if (!isStreamAffectedByRingerMode(streamType)) continue;
- // Either silent or vibrate, either way volume is 0
- setStreamVolumeInt(streamType, 0, false);
+ if (isStreamAffectedByRingerMode(streamType)) {
+ // Either silent or vibrate, either way volume is 0
+ setStreamVolumeInt(streamType, 0, false, false);
+ } else {
+ // restore stream volume in the case the stream changed from affected
+ // to non affected by ringer mode. Does not arm to do it for streams that
+ // are not affected as well.
+ setStreamVolumeInt(streamType, mStreamStates[streamType].mLastAudibleIndex,
+ false, false);
+ }
}
}
@@ -621,7 +636,7 @@
int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
int index = mStreamStates[streamType].mIndex;
syncRingerAndNotificationStreamVolume(streamType, index, true);
- setStreamVolumeInt(streamType, index, true);
+ setStreamVolumeInt(streamType, index, true, true);
}
}
@@ -791,7 +806,7 @@
int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
int index = mStreamStates[streamType].mIndex;
syncRingerAndNotificationStreamVolume(streamType, index, true);
- setStreamVolumeInt(streamType, index, true);
+ setStreamVolumeInt(streamType, index, true, true);
}
}
}
@@ -941,9 +956,7 @@
}
public boolean isStreamAffectedByRingerMode(int streamType) {
- int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
- Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0);
- return (ringerModeAffectedStreams & (1 << streamType)) != 0;
+ return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
}
public boolean isStreamAffectedByMute(int streamType) {
@@ -1095,15 +1108,15 @@
}
public boolean adjustIndex(int deltaIndex) {
- return setIndex(mIndex + deltaIndex);
+ return setIndex(mIndex + deltaIndex, true);
}
- public boolean setIndex(int index) {
+ public boolean setIndex(int index, boolean lastAudible) {
int oldIndex = mIndex;
mIndex = getValidIndex(index);
if (oldIndex != mIndex) {
- if (mIndex > 0) {
+ if (lastAudible) {
mLastAudibleIndex = mIndex;
}
return true;
@@ -1153,7 +1166,7 @@
mDeathHandlers.add(this);
// If the stream is not yet muted by any client, set lvel to 0
if (muteCount() == 0) {
- setIndex(0);
+ setIndex(0, false);
sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, mStreamType, SENDMSG_NOOP, 0, 0,
VolumeStreamState.this, 0);
}
@@ -1180,7 +1193,7 @@
// If the stream is not mut any more, restore it's volume if
// ringer mode allows it
if (!isStreamAffectedByRingerMode(mStreamType) || mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
- setIndex(mLastAudibleIndex);
+ setIndex(mLastAudibleIndex, false);
sendMsg(mAudioHandler, MSG_SET_SYSTEM_VOLUME, mStreamType, SENDMSG_NOOP, 0, 0,
VolumeStreamState.this, 0);
}
@@ -1405,6 +1418,10 @@
public void onChange(boolean selfChange) {
super.onChange(selfChange);
+ mRingerModeAffectedStreams = Settings.System.getInt(mContentResolver,
+ Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ 0);
+
/*
* Ensure all stream types that should be affected by ringer mode
* are in the proper state.