am 742647c8: Merge "AudioService: removed last audible volume index" into jb-mr2-dev

* commit '742647c809622703207c34171d482c562e34b10b':
  AudioService: removed last audible volume index
This commit is contained in:
Eric Laurent
2013-04-02 08:24:26 -07:00
committed by Android Git Automerger

View File

@ -169,11 +169,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
private static final int MSG_RCC_NEW_PLAYBACK_STATE = 32; private static final int MSG_RCC_NEW_PLAYBACK_STATE = 32;
// flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
// persisted
private static final int PERSIST_CURRENT = 0x1;
private static final int PERSIST_LAST_AUDIBLE = 0x2;
private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
// Timeout for connection to bluetooth headset service // Timeout for connection to bluetooth headset service
private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
@ -582,14 +577,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
for (int streamType = 0; streamType < numStreamTypes; streamType++) { for (int streamType = 0; streamType < numStreamTypes; streamType++) {
if (streamType != mStreamVolumeAlias[streamType]) { if (streamType != mStreamVolumeAlias[streamType]) {
mStreamStates[streamType]. mStreamStates[streamType].
setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]);
false /*lastAudible*/);
mStreamStates[streamType].
setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]],
true /*lastAudible*/);
} }
// apply stream volume // apply stream volume
if (mStreamStates[streamType].muteCount() == 0) { if (!mStreamStates[streamType].isMuted()) {
mStreamStates[streamType].applyAllVolumes(); mStreamStates[streamType].applyAllVolumes();
} }
} }
@ -633,10 +624,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
} }
mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
if (updateVolumes) { if (updateVolumes) {
mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias], mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]);
false /*lastAudible*/);
mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
true /*lastAudible*/);
sendMsg(mAudioHandler, sendMsg(mAudioHandler,
MSG_SET_ALL_VOLUMES, MSG_SET_ALL_VOLUMES,
SENDMSG_QUEUE, SENDMSG_QUEUE,
@ -836,14 +824,9 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
final int device = getDeviceForStream(streamTypeAlias); final int device = getDeviceForStream(streamTypeAlias);
// get last audible index if stream is muted, current index otherwise int aliasIndex = streamState.getIndex(device);
int aliasIndex = streamState.getIndex(device,
(streamState.muteCount() != 0) /* lastAudible */);
boolean adjustVolume = true; boolean adjustVolume = true;
int step; int step;
int index;
int oldIndex;
// reset any pending volume command // reset any pending volume command
synchronized (mSafeMediaVolumeState) { synchronized (mSafeMediaVolumeState) {
@ -872,64 +855,40 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
step = rescaleIndex(10, streamType, streamTypeAlias); step = rescaleIndex(10, streamType, streamTypeAlias);
} }
if ((direction == AudioManager.ADJUST_RAISE) && // If either the client forces allowing ringer modes for this adjustment,
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { // or the stream type is one that is affected by ringer modes
index = mStreamStates[streamType].getIndex(device, if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(streamState.muteCount() != 0) /* lastAudible */); (streamTypeAlias == getMasterStreamType())) {
oldIndex = index; int ringerMode = getRingerMode();
mVolumePanel.postDisplaySafeVolumeWarning(flags); // do not vibrate if already in vibrate mode
} else { if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
// If either the client forces allowing ringer modes for this adjustment, flags &= ~AudioManager.FLAG_VIBRATE;
// or the stream type is one that is affected by ringer modes
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(streamTypeAlias == getMasterStreamType())) {
int ringerMode = getRingerMode();
// do not vibrate if already in vibrate mode
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
flags &= ~AudioManager.FLAG_VIBRATE;
}
// Check if the ringer mode changes with this volume adjustment. If
// it does, it will handle adjusting the volume, so we won't below
adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
if ((streamTypeAlias == getMasterStreamType()) &&
(mRingerMode == AudioManager.RINGER_MODE_SILENT)) {
streamState.setLastAudibleIndex(0, device);
}
} }
// Check if the ringer mode changes with this volume adjustment. If
// it does, it will handle adjusting the volume, so we won't below
adjustVolume = checkForRingerModeChange(aliasIndex, direction, step);
}
// If stream is muted, adjust last audible index only int oldIndex = mStreamStates[streamType].getIndex(device);
oldIndex = mStreamStates[streamType].getIndex(device,
(mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
if (streamState.muteCount() != 0) { if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
if (adjustVolume) { if ((direction == AudioManager.ADJUST_RAISE) &&
// Post a persist volume msg !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
// no need to persist volume on all streams sharing the same alias Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
streamState.adjustLastAudibleIndex(direction * step, device); mVolumePanel.postDisplaySafeVolumeWarning(flags);
sendMsg(mAudioHandler, } else if (streamState.adjustIndex(direction * step, device)) {
MSG_PERSIST_VOLUME, // Post message to set system volume (it in turn will post a message
SENDMSG_QUEUE, // to persist). Do not change volume if stream is muted.
PERSIST_LAST_AUDIBLE, sendMsg(mAudioHandler,
device, MSG_SET_DEVICE_VOLUME,
streamState, SENDMSG_QUEUE,
PERSIST_DELAY); device,
} 0,
index = mStreamStates[streamType].getIndex(device, true /* lastAudible */); streamState,
} else { 0);
if (adjustVolume && streamState.adjustIndex(direction * step, device)) {
// Post message to set system volume (it in turn will post a message
// to persist). Do not change volume if stream is muted.
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
}
index = mStreamStates[streamType].getIndex(device, false /* lastAudible */);
} }
} }
int index = mStreamStates[streamType].getIndex(device);
sendVolumeUpdate(streamType, oldIndex, index, flags); sendVolumeUpdate(streamType, oldIndex, index, flags);
} }
@ -969,6 +928,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
}; };
private void onSetStreamVolume(int streamType, int index, int flags, int device) { private void onSetStreamVolume(int streamType, int index, int flags, int device) {
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false);
// setting volume on master stream type also controls silent mode // setting volume on master stream type also controls silent mode
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
(mStreamVolumeAlias[streamType] == getMasterStreamType())) { (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
@ -976,18 +936,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
if (index == 0) { if (index == 0) {
newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
: AudioManager.RINGER_MODE_SILENT; : AudioManager.RINGER_MODE_SILENT;
setStreamVolumeInt(mStreamVolumeAlias[streamType],
index,
device,
false,
true);
} else { } else {
newRingerMode = AudioManager.RINGER_MODE_NORMAL; newRingerMode = AudioManager.RINGER_MODE_NORMAL;
} }
setRingerMode(newRingerMode); setRingerMode(newRingerMode);
} }
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false, true);
} }
/** @see AudioManager#setStreamVolume(int, int, int) */ /** @see AudioManager#setStreamVolume(int, int, int) */
@ -1006,9 +959,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// reset any pending volume command // reset any pending volume command
mPendingVolumeCommand = null; mPendingVolumeCommand = null;
// get last audible index if stream is muted, current index otherwise oldIndex = streamState.getIndex(device);
oldIndex = streamState.getIndex(device,
(streamState.muteCount() != 0) /* lastAudible */);
index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]); index = rescaleIndex(index * 10, streamType, mStreamVolumeAlias[streamType]);
@ -1034,9 +985,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
streamType, index, flags, device); streamType, index, flags, device);
} else { } else {
onSetStreamVolume(streamType, index, flags, device); onSetStreamVolume(streamType, index, flags, device);
// get last audible index if stream is muted, current index otherwise index = mStreamStates[streamType].getIndex(device);
index = mStreamStates[streamType].getIndex(device,
(mStreamStates[streamType].muteCount() != 0) /* lastAudible */);
} }
} }
sendVolumeUpdate(streamType, oldIndex, index, flags); sendVolumeUpdate(streamType, oldIndex, index, flags);
@ -1198,41 +1147,23 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
* @param device the device whose volume must be changed * @param device the device whose volume must be changed
* @param force If true, set the volume even if the desired volume is same * @param force If true, set the volume even if the desired volume is same
* as the current volume. * as the current volume.
* @param lastAudible If true, stores new index as last audible one
*/ */
private void setStreamVolumeInt(int streamType, private void setStreamVolumeInt(int streamType,
int index, int index,
int device, int device,
boolean force, boolean force) {
boolean lastAudible) {
VolumeStreamState streamState = mStreamStates[streamType]; VolumeStreamState streamState = mStreamStates[streamType];
// If stream is muted, set last audible index only if (streamState.setIndex(index, device) || force) {
if (streamState.muteCount() != 0) { // Post message to set system volume (it in turn will post a message
// Do not allow last audible index to be 0 // to persist).
if (index != 0) { sendMsg(mAudioHandler,
streamState.setLastAudibleIndex(index, device); MSG_SET_DEVICE_VOLUME,
// Post a persist volume msg SENDMSG_QUEUE,
sendMsg(mAudioHandler, device,
MSG_PERSIST_VOLUME, 0,
SENDMSG_QUEUE, streamState,
PERSIST_LAST_AUDIBLE, 0);
device,
streamState,
PERSIST_DELAY);
}
} else {
if (streamState.setIndex(index, device, lastAudible) || force) {
// Post message to set system volume (it in turn will post a message
// to persist).
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
}
} }
} }
@ -1244,7 +1175,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
for (int stream = 0; stream < mStreamStates.length; stream++) { for (int stream = 0; stream < mStreamStates.length; stream++) {
if (!isStreamAffectedByMute(stream) || stream == streamType) continue; if (!isStreamAffectedByMute(stream) || stream == streamType) continue;
// Bring back last audible volume
mStreamStates[stream].mute(cb, state); mStreamStates[stream].mute(cb, state);
} }
} }
@ -1262,7 +1192,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
/** get stream mute state. */ /** get stream mute state. */
public boolean isStreamMute(int streamType) { public boolean isStreamMute(int streamType) {
return (mStreamStates[streamType].muteCount() != 0); return mStreamStates[streamType].isMuted();
} }
/** @see AudioManager#setMasterMute(boolean, int) */ /** @see AudioManager#setMasterMute(boolean, int) */
@ -1289,8 +1219,12 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
public int getStreamVolume(int streamType) { public int getStreamVolume(int streamType) {
ensureValidStreamType(streamType); ensureValidStreamType(streamType);
int device = getDeviceForStream(streamType); int device = getDeviceForStream(streamType);
int index = mStreamStates[streamType].getIndex(device, false /* lastAudible */); int index = mStreamStates[streamType].getIndex(device);
// by convention getStreamVolume() returns 0 when a stream is muted.
if (mStreamStates[streamType].isMuted()) {
index = 0;
}
if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
(device & mFixedVolumeDevices) != 0) { (device & mFixedVolumeDevices) != 0) {
index = mStreamStates[streamType].getMaxIndex(); index = mStreamStates[streamType].getMaxIndex();
@ -1347,7 +1281,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
public int getLastAudibleStreamVolume(int streamType) { public int getLastAudibleStreamVolume(int streamType) {
ensureValidStreamType(streamType); ensureValidStreamType(streamType);
int device = getDeviceForStream(streamType); int device = getDeviceForStream(streamType);
return (mStreamStates[streamType].getIndex(device, true /* lastAudible */) + 5) / 10; return (mStreamStates[streamType].getIndex(device) + 5) / 10;
} }
/** Get last audible master volume before it was muted. */ /** Get last audible master volume before it was muted. */
@ -1412,7 +1346,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
if (mVoiceCapable && if (mVoiceCapable &&
mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
synchronized (mStreamStates[streamType]) { synchronized (mStreamStates[streamType]) {
Set set = mStreamStates[streamType].mLastAudibleIndex.entrySet(); Set set = mStreamStates[streamType].mIndex.entrySet();
Iterator i = set.iterator(); Iterator i = set.iterator();
while (i.hasNext()) { while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next(); Map.Entry entry = (Map.Entry)i.next();
@ -1661,8 +1595,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
streamType = AudioManager.STREAM_MUSIC; streamType = AudioManager.STREAM_MUSIC;
} }
int device = getDeviceForStream(streamType); int device = getDeviceForStream(streamType);
int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device, false); int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, false); setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true);
updateStreamVolumeAlias(true /*updateVolumes*/); updateStreamVolumeAlias(true /*updateVolumes*/);
} }
@ -1896,7 +1830,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
streamState.readSettings(); streamState.readSettings();
// unmute stream that was muted but is not affect by mute anymore // unmute stream that was muted but is not affect by mute anymore
if (streamState.muteCount() != 0 && ((!isStreamAffectedByMute(streamType) && if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) &&
!isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) {
int size = streamState.mDeathHandlers.size(); int size = streamState.mDeathHandlers.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
@ -2396,8 +2330,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
0, 0,
null, null,
MUSIC_ACTIVE_POLL_PERIOD_MS); MUSIC_ACTIVE_POLL_PERIOD_MS);
int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device, int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
false /*lastAudible*/);
if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
(index > mSafeMediaVolumeIndex)) { (index > mSafeMediaVolumeIndex)) {
// Approximate cumulative active music time // Approximate cumulative active music time
@ -2742,18 +2675,14 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
private final int mStreamType; private final int mStreamType;
private String mVolumeIndexSettingName; private String mVolumeIndexSettingName;
private String mLastAudibleVolumeIndexSettingName;
private int mIndexMax; private int mIndexMax;
private final ConcurrentHashMap<Integer, Integer> mIndex = private final ConcurrentHashMap<Integer, Integer> mIndex =
new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
private final ConcurrentHashMap<Integer, Integer> mLastAudibleIndex =
new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4);
private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death
private VolumeStreamState(String settingName, int streamType) { private VolumeStreamState(String settingName, int streamType) {
mVolumeIndexSettingName = settingName; mVolumeIndexSettingName = settingName;
mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
mStreamType = streamType; mStreamType = streamType;
mIndexMax = MAX_STREAM_VOLUME[streamType]; mIndexMax = MAX_STREAM_VOLUME[streamType];
@ -2766,10 +2695,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
readSettings(); readSettings();
} }
public String getSettingNameForDevice(boolean lastAudible, int device) { public String getSettingNameForDevice(int device) {
String name = lastAudible ? String name = mVolumeIndexSettingName;
mLastAudibleVolumeIndexSettingName :
mVolumeIndexSettingName;
String suffix = AudioSystem.getDeviceName(device); String suffix = AudioSystem.getDeviceName(device);
if (suffix.isEmpty()) { if (suffix.isEmpty()) {
return name; return name;
@ -2781,14 +2708,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// force maximum volume on all streams if fixed volume property is set // force maximum volume on all streams if fixed volume property is set
if (mUseFixedVolume) { if (mUseFixedVolume) {
mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
return; return;
} }
// do not read system stream volume from settings: this stream is always aliased // do not read system stream volume from settings: this stream is always aliased
// to another stream type and its volume is never persisted. Values in settings can // to another stream type and its volume is never persisted. Values in settings can
// only be stale values // only be stale values
// on first call to readSettings() at init time, muteCount() is always 0 so we will
// always create entries for default device
if ((mStreamType == AudioSystem.STREAM_SYSTEM) || if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
(mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]; int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
@ -2797,10 +2721,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
index = mIndexMax; index = mIndexMax;
} }
} }
if (muteCount() == 0) { mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
}
mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
return; return;
} }
@ -2814,7 +2735,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
remainingDevices &= ~device; remainingDevices &= ~device;
// retrieve current volume for device // retrieve current volume for device
String name = getSettingNameForDevice(false /* lastAudible */, device); String name = getSettingNameForDevice(device);
// if no volume stored for current stream and device, use default volume if default // if no volume stored for current stream and device, use default volume if default
// device, continue otherwise // device, continue otherwise
int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
@ -2828,72 +2749,33 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// ignore settings for fixed volume devices: volume should always be at max or 0 // ignore settings for fixed volume devices: volume should always be at max or 0
if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) && if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
((device & mFixedVolumeDevices) != 0)) { ((device & mFixedVolumeDevices) != 0)) {
if ((muteCount()) == 0 && (index != 0)) { mIndex.put(device, (index != 0) ? mIndexMax : 0);
mIndex.put(device, mIndexMax); } else {
} else {
mIndex.put(device, 0);
}
mLastAudibleIndex.put(device, mIndexMax);
continue;
}
// retrieve last audible volume for device
name = getSettingNameForDevice(true /* lastAudible */, device);
// use stored last audible index if present, otherwise use current index if not 0
// or default index
defaultIndex = (index > 0) ?
index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
int lastAudibleIndex = Settings.System.getIntForUser(
mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
// a last audible index of 0 should never be stored for ring and notification
// streams on phones (voice capable devices).
if ((lastAudibleIndex == 0) && mVoiceCapable &&
(mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_RING)) {
lastAudibleIndex = AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
// Correct the data base
sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME,
SENDMSG_QUEUE,
PERSIST_LAST_AUDIBLE,
device,
this,
PERSIST_DELAY);
}
mLastAudibleIndex.put(device, getValidIndex(10 * lastAudibleIndex));
// the initial index should never be 0 for ring and notification streams on phones
// (voice capable devices) if not in silent or vibrate mode.
if ((index == 0) && (mRingerMode == AudioManager.RINGER_MODE_NORMAL) &&
mVoiceCapable &&
(mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_RING)) {
index = lastAudibleIndex;
// Correct the data base
sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME,
SENDMSG_QUEUE,
PERSIST_CURRENT,
device,
this,
PERSIST_DELAY);
}
if (muteCount() == 0) {
mIndex.put(device, getValidIndex(10 * index)); mIndex.put(device, getValidIndex(10 * index));
} }
} }
} }
public void applyDeviceVolume(int device) { public void applyDeviceVolume(int device) {
AudioSystem.setStreamVolumeIndex(mStreamType, int index;
(getIndex(device, false /* lastAudible */) + 5)/10, if (isMuted()) {
device); index = 0;
} else {
index = (getIndex(device) + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
} }
public synchronized void applyAllVolumes() { public synchronized void applyAllVolumes() {
// apply default volume first: by convention this will reset all // apply default volume first: by convention this will reset all
// devices volumes in audio policy manager to the supplied value // devices volumes in audio policy manager to the supplied value
AudioSystem.setStreamVolumeIndex(mStreamType, int index;
(getIndex(AudioSystem.DEVICE_OUT_DEFAULT, false /* lastAudible */) + 5)/10, if (isMuted()) {
AudioSystem.DEVICE_OUT_DEFAULT); index = 0;
} else {
index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
// then apply device specific volumes // then apply device specific volumes
Set set = mIndex.entrySet(); Set set = mIndex.entrySet();
Iterator i = set.iterator(); Iterator i = set.iterator();
@ -2901,22 +2783,23 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
Map.Entry entry = (Map.Entry)i.next(); Map.Entry entry = (Map.Entry)i.next();
int device = ((Integer)entry.getKey()).intValue(); int device = ((Integer)entry.getKey()).intValue();
if (device != AudioSystem.DEVICE_OUT_DEFAULT) { if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
AudioSystem.setStreamVolumeIndex(mStreamType, if (isMuted()) {
((Integer)entry.getValue() + 5)/10, index = 0;
device); } else {
index = ((Integer)entry.getValue() + 5)/10;
}
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
} }
} }
} }
public boolean adjustIndex(int deltaIndex, int device) { public boolean adjustIndex(int deltaIndex, int device) {
return setIndex(getIndex(device, return setIndex(getIndex(device) + deltaIndex,
false /* lastAudible */) + deltaIndex, device);
device,
true /* lastAudible */);
} }
public synchronized boolean setIndex(int index, int device, boolean lastAudible) { public synchronized boolean setIndex(int index, int device) {
int oldIndex = getIndex(device, false /* lastAudible */); int oldIndex = getIndex(device);
index = getValidIndex(index); index = getValidIndex(index);
synchronized (mCameraSoundForced) { synchronized (mCameraSoundForced) {
if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
@ -2926,9 +2809,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mIndex.put(device, index); mIndex.put(device, index);
if (oldIndex != index) { if (oldIndex != index) {
if (lastAudible) {
mLastAudibleIndex.put(device, index);
}
// Apply change to all streams using this one as alias // Apply change to all streams using this one as alias
// if changing volume of current device, also change volume of current // if changing volume of current device, also change volume of current
// device on aliased stream // device on aliased stream
@ -2939,12 +2819,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mStreamVolumeAlias[streamType] == mStreamType) { mStreamVolumeAlias[streamType] == mStreamType) {
int scaledIndex = rescaleIndex(index, mStreamType, streamType); int scaledIndex = rescaleIndex(index, mStreamType, streamType);
mStreamStates[streamType].setIndex(scaledIndex, mStreamStates[streamType].setIndex(scaledIndex,
device, device);
lastAudible);
if (currentDevice) { if (currentDevice) {
mStreamStates[streamType].setIndex(scaledIndex, mStreamStates[streamType].setIndex(scaledIndex,
getDeviceForStream(streamType), getDeviceForStream(streamType));
lastAudible);
} }
} }
} }
@ -2954,63 +2832,21 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
} }
} }
public synchronized int getIndex(int device, boolean lastAudible) { public synchronized int getIndex(int device) {
ConcurrentHashMap <Integer, Integer> indexes; Integer index = mIndex.get(device);
if (lastAudible) {
indexes = mLastAudibleIndex;
} else {
indexes = mIndex;
}
Integer index = indexes.get(device);
if (index == null) { if (index == null) {
// there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
index = indexes.get(AudioSystem.DEVICE_OUT_DEFAULT); index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT);
} }
return index.intValue(); return index.intValue();
} }
public synchronized void setLastAudibleIndex(int index, int device) {
// Apply change to all streams using this one as alias
// if changing volume of current device, also change volume of current
// device on aliased stream
boolean currentDevice = (device == getDeviceForStream(mStreamType));
int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
if (streamType != mStreamType &&
mStreamVolumeAlias[streamType] == mStreamType) {
int scaledIndex = rescaleIndex(index, mStreamType, streamType);
mStreamStates[streamType].setLastAudibleIndex(scaledIndex, device);
if (currentDevice) {
mStreamStates[streamType].setLastAudibleIndex(scaledIndex,
getDeviceForStream(streamType));
}
}
}
mLastAudibleIndex.put(device, getValidIndex(index));
}
public synchronized void adjustLastAudibleIndex(int deltaIndex, int device) {
setLastAudibleIndex(getIndex(device,
true /* lastAudible */) + deltaIndex,
device);
}
public int getMaxIndex() { public int getMaxIndex() {
return mIndexMax; return mIndexMax;
} }
// only called by setAllIndexes() which is already synchronized public synchronized void setAllIndexes(VolumeStreamState srcStream) {
public ConcurrentHashMap <Integer, Integer> getAllIndexes(boolean lastAudible) { Set set = srcStream.mIndex.entrySet();
if (lastAudible) {
return mLastAudibleIndex;
} else {
return mIndex;
}
}
public synchronized void setAllIndexes(VolumeStreamState srcStream, boolean lastAudible) {
ConcurrentHashMap <Integer, Integer> indexes = srcStream.getAllIndexes(lastAudible);
Set set = indexes.entrySet();
Iterator i = set.iterator(); Iterator i = set.iterator();
while (i.hasNext()) { while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next(); Map.Entry entry = (Map.Entry)i.next();
@ -3018,11 +2854,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
int index = ((Integer)entry.getValue()).intValue(); int index = ((Integer)entry.getValue()).intValue();
index = rescaleIndex(index, srcStream.getStreamType(), mStreamType); index = rescaleIndex(index, srcStream.getStreamType(), mStreamType);
if (lastAudible) { setIndex(index, device);
setLastAudibleIndex(index, device);
} else {
setIndex(index, device, false /* lastAudible */);
}
} }
} }
@ -3033,12 +2865,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
Map.Entry entry = (Map.Entry)i.next(); Map.Entry entry = (Map.Entry)i.next();
entry.setValue(mIndexMax); entry.setValue(mIndexMax);
} }
set = mLastAudibleIndex.entrySet();
i = set.iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
entry.setValue(mIndexMax);
}
} }
public synchronized void mute(IBinder cb, boolean state) { public synchronized void mute(IBinder cb, boolean state) {
@ -3074,6 +2900,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
// must be called while synchronized on parent VolumeStreamState // must be called while synchronized on parent VolumeStreamState
public void mute(boolean state) { public void mute(boolean state) {
boolean updateVolume = false;
if (state) { if (state) {
if (mMuteCount == 0) { if (mMuteCount == 0) {
// Register for client death notification // Register for client death notification
@ -3082,22 +2909,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
if (mICallback != null) { if (mICallback != null) {
mICallback.linkToDeath(this, 0); mICallback.linkToDeath(this, 0);
} }
mDeathHandlers.add(this); VolumeStreamState.this.mDeathHandlers.add(this);
// If the stream is not yet muted by any client, set level to 0 // If the stream is not yet muted by any client, set level to 0
if (muteCount() == 0) { if (!VolumeStreamState.this.isMuted()) {
Set set = mIndex.entrySet(); updateVolume = true;
Iterator i = set.iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
int device = ((Integer)entry.getKey()).intValue();
setIndex(0, device, false /* lastAudible */);
}
sendMsg(mAudioHandler,
MSG_SET_ALL_VOLUMES,
SENDMSG_QUEUE,
0,
0,
VolumeStreamState.this, 0);
} }
} catch (RemoteException e) { } catch (RemoteException e) {
// Client has died! // Client has died!
@ -3115,37 +2930,25 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mMuteCount--; mMuteCount--;
if (mMuteCount == 0) { if (mMuteCount == 0) {
// Unregister from client death notification // Unregister from client death notification
mDeathHandlers.remove(this); VolumeStreamState.this.mDeathHandlers.remove(this);
// mICallback can be 0 if muted by AudioService // mICallback can be 0 if muted by AudioService
if (mICallback != null) { if (mICallback != null) {
mICallback.unlinkToDeath(this, 0); mICallback.unlinkToDeath(this, 0);
} }
if (muteCount() == 0) { if (!VolumeStreamState.this.isMuted()) {
// If the stream is not muted any more, restore its volume if updateVolume = true;
// ringer mode allows it
if (!isStreamAffectedByRingerMode(mStreamType) ||
mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
Set set = mIndex.entrySet();
Iterator i = set.iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
int device = ((Integer)entry.getKey()).intValue();
setIndex(getIndex(device,
true /* lastAudible */),
device,
false /* lastAudible */);
}
sendMsg(mAudioHandler,
MSG_SET_ALL_VOLUMES,
SENDMSG_QUEUE,
0,
0,
VolumeStreamState.this, 0);
}
} }
} }
} }
} }
if (updateVolume) {
sendMsg(mAudioHandler,
MSG_SET_ALL_VOLUMES,
SENDMSG_QUEUE,
0,
0,
VolumeStreamState.this, 0);
}
} }
public void binderDied() { public void binderDied() {
@ -3167,6 +2970,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
return count; return count;
} }
private synchronized boolean isMuted() {
return muteCount() != 0;
}
// only called by mute() which is already synchronized // only called by mute() which is already synchronized
private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) { private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) {
VolumeDeathHandler handler; VolumeDeathHandler handler;
@ -3199,14 +3006,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue()) pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue())
+ ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", "); + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", ");
} }
pw.print("\n Last audible: ");
set = mLastAudibleIndex.entrySet();
i = set.iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue())
+ ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", ");
}
} }
} }
@ -3254,8 +3053,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
sendMsg(mAudioHandler, sendMsg(mAudioHandler,
MSG_PERSIST_VOLUME, MSG_PERSIST_VOLUME,
SENDMSG_QUEUE, SENDMSG_QUEUE,
PERSIST_CURRENT|PERSIST_LAST_AUDIBLE,
device, device,
0,
streamState, streamState,
PERSIST_DELAY); PERSIST_DELAY);
@ -3276,24 +3075,14 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
} }
} }
private void persistVolume(VolumeStreamState streamState, private void persistVolume(VolumeStreamState streamState, int device) {
int persistType,
int device) {
if (mUseFixedVolume) { if (mUseFixedVolume) {
return; return;
} }
if ((persistType & PERSIST_CURRENT) != 0) { System.putIntForUser(mContentResolver,
System.putIntForUser(mContentResolver, streamState.getSettingNameForDevice(device),
streamState.getSettingNameForDevice(false /* lastAudible */, device), (streamState.getIndex(device) + 5)/ 10,
(streamState.getIndex(device, false /* lastAudible */) + 5)/ 10, UserHandle.USER_CURRENT);
UserHandle.USER_CURRENT);
}
if ((persistType & PERSIST_LAST_AUDIBLE) != 0) {
System.putIntForUser(mContentResolver,
streamState.getSettingNameForDevice(true /* lastAudible */, device),
(streamState.getIndex(device, true /* lastAudible */) + 5) / 10,
UserHandle.USER_CURRENT);
}
} }
private void persistRingerMode(int ringerMode) { private void persistRingerMode(int ringerMode) {
@ -3545,7 +3334,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
break; break;
case MSG_PERSIST_VOLUME: case MSG_PERSIST_VOLUME:
persistVolume((VolumeStreamState) msg.obj, msg.arg1, msg.arg2); persistVolume((VolumeStreamState) msg.obj, msg.arg1);
break; break;
case MSG_PERSIST_MASTER_VOLUME: case MSG_PERSIST_MASTER_VOLUME:
@ -6391,10 +6180,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
mRingerModeAffectedStreams &= mRingerModeAffectedStreams &=
~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
} else { } else {
s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]);
false /*lastAudible*/);
s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM],
true /*lastAudible*/);
mRingerModeAffectedStreams |= mRingerModeAffectedStreams |=
(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
} }
@ -6540,7 +6326,6 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
private void enforceSafeMediaVolume() { private void enforceSafeMediaVolume() {
VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
boolean lastAudible = (streamState.muteCount() != 0);
int devices = mSafeMediaVolumeDevices; int devices = mSafeMediaVolumeDevices;
int i = 0; int i = 0;
@ -6549,27 +6334,16 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
if ((device & devices) == 0) { if ((device & devices) == 0) {
continue; continue;
} }
int index = streamState.getIndex(device, lastAudible); int index = streamState.getIndex(device);
if (index > mSafeMediaVolumeIndex) { if (index > mSafeMediaVolumeIndex) {
if (lastAudible) { streamState.setIndex(mSafeMediaVolumeIndex, device);
streamState.setLastAudibleIndex(mSafeMediaVolumeIndex, device); sendMsg(mAudioHandler,
sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME,
MSG_PERSIST_VOLUME, SENDMSG_QUEUE,
SENDMSG_QUEUE, device,
PERSIST_LAST_AUDIBLE, 0,
device, streamState,
streamState, 0);
PERSIST_DELAY);
} else {
streamState.setIndex(mSafeMediaVolumeIndex, device, true);
sendMsg(mAudioHandler,
MSG_SET_DEVICE_VOLUME,
SENDMSG_QUEUE,
device,
0,
streamState,
0);
}
} }
devices &= ~device; devices &= ~device;
} }