am ba64d298: Merge "AudioService: fix cross deadlock in VolumeStreamState"
* commit 'ba64d298bee228b8e27ea17fb31fbff4b4188304': AudioService: fix cross deadlock in VolumeStreamState
This commit is contained in:
@@ -2863,54 +2863,56 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
return name + "_" + suffix;
|
return name + "_" + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void readSettings() {
|
public void readSettings() {
|
||||||
// force maximum volume on all streams if fixed volume property is set
|
synchronized (VolumeStreamState.class) {
|
||||||
if (mUseFixedVolume) {
|
// force maximum volume on all streams if fixed volume property is set
|
||||||
mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
|
if (mUseFixedVolume) {
|
||||||
return;
|
mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
|
||||||
}
|
return;
|
||||||
// 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
|
// do not read system stream volume from settings: this stream is always aliased
|
||||||
// only be stale values
|
// to another stream type and its volume is never persisted. Values in settings can
|
||||||
if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
|
// only be stale values
|
||||||
(mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
|
if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
|
||||||
int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
|
(mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
|
||||||
synchronized (mCameraSoundForced) {
|
int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
|
||||||
if (mCameraSoundForced) {
|
synchronized (mCameraSoundForced) {
|
||||||
index = mIndexMax;
|
if (mCameraSoundForced) {
|
||||||
|
index = mIndexMax;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
|
||||||
mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
|
|
||||||
|
|
||||||
for (int i = 0; remainingDevices != 0; i++) {
|
|
||||||
int device = (1 << i);
|
|
||||||
if ((device & remainingDevices) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
remainingDevices &= ~device;
|
|
||||||
|
|
||||||
// retrieve current volume for device
|
|
||||||
String name = getSettingNameForDevice(device);
|
|
||||||
// if no volume stored for current stream and device, use default volume if default
|
|
||||||
// device, continue otherwise
|
|
||||||
int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
|
|
||||||
AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
|
|
||||||
int index = Settings.System.getIntForUser(
|
|
||||||
mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
|
|
||||||
if (index == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore settings for fixed volume devices: volume should always be at max or 0
|
int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
|
||||||
if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
|
|
||||||
((device & mFixedVolumeDevices) != 0)) {
|
for (int i = 0; remainingDevices != 0; i++) {
|
||||||
mIndex.put(device, (index != 0) ? mIndexMax : 0);
|
int device = (1 << i);
|
||||||
} else {
|
if ((device & remainingDevices) == 0) {
|
||||||
mIndex.put(device, getValidIndex(10 * index));
|
continue;
|
||||||
|
}
|
||||||
|
remainingDevices &= ~device;
|
||||||
|
|
||||||
|
// retrieve current volume for device
|
||||||
|
String name = getSettingNameForDevice(device);
|
||||||
|
// if no volume stored for current stream and device, use default volume if default
|
||||||
|
// device, continue otherwise
|
||||||
|
int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
|
||||||
|
AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
|
||||||
|
int index = Settings.System.getIntForUser(
|
||||||
|
mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
|
||||||
|
if (index == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore settings for fixed volume devices: volume should always be at max or 0
|
||||||
|
if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
|
||||||
|
((device & mFixedVolumeDevices) != 0)) {
|
||||||
|
mIndex.put(device, (index != 0) ? mIndexMax : 0);
|
||||||
|
} else {
|
||||||
|
mIndex.put(device, getValidIndex(10 * index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2928,32 +2930,34 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
|
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void applyAllVolumes() {
|
public void applyAllVolumes() {
|
||||||
// apply default volume first: by convention this will reset all
|
synchronized (VolumeStreamState.class) {
|
||||||
// devices volumes in audio policy manager to the supplied value
|
// apply default volume first: by convention this will reset all
|
||||||
int index;
|
// devices volumes in audio policy manager to the supplied value
|
||||||
if (isMuted()) {
|
int index;
|
||||||
index = 0;
|
if (isMuted()) {
|
||||||
} else {
|
index = 0;
|
||||||
index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
|
} else {
|
||||||
}
|
index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
|
||||||
AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
|
}
|
||||||
// then apply device specific volumes
|
AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
|
||||||
Set set = mIndex.entrySet();
|
// then apply device specific volumes
|
||||||
Iterator i = set.iterator();
|
Set set = mIndex.entrySet();
|
||||||
while (i.hasNext()) {
|
Iterator i = set.iterator();
|
||||||
Map.Entry entry = (Map.Entry)i.next();
|
while (i.hasNext()) {
|
||||||
int device = ((Integer)entry.getKey()).intValue();
|
Map.Entry entry = (Map.Entry)i.next();
|
||||||
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
|
int device = ((Integer)entry.getKey()).intValue();
|
||||||
if (isMuted()) {
|
if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
|
||||||
index = 0;
|
if (isMuted()) {
|
||||||
} else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
|
index = 0;
|
||||||
mAvrcpAbsVolSupported) {
|
} else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
|
||||||
index = (mIndexMax + 5)/10;
|
mAvrcpAbsVolSupported) {
|
||||||
} else {
|
index = (mIndexMax + 5)/10;
|
||||||
index = ((Integer)entry.getValue() + 5)/10;
|
} else {
|
||||||
|
index = ((Integer)entry.getValue() + 5)/10;
|
||||||
|
}
|
||||||
|
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
|
||||||
}
|
}
|
||||||
AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2963,94 +2967,104 @@ public class AudioService extends IAudioService.Stub {
|
|||||||
device);
|
device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean setIndex(int index, int device) {
|
public boolean setIndex(int index, int device) {
|
||||||
int oldIndex = getIndex(device);
|
synchronized (VolumeStreamState.class) {
|
||||||
index = getValidIndex(index);
|
int oldIndex = getIndex(device);
|
||||||
synchronized (mCameraSoundForced) {
|
index = getValidIndex(index);
|
||||||
if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
|
synchronized (mCameraSoundForced) {
|
||||||
index = mIndexMax;
|
if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
|
||||||
}
|
index = mIndexMax;
|
||||||
}
|
|
||||||
mIndex.put(device, index);
|
|
||||||
|
|
||||||
if (oldIndex != index) {
|
|
||||||
// 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].setIndex(scaledIndex,
|
|
||||||
device);
|
|
||||||
if (currentDevice) {
|
|
||||||
mStreamStates[streamType].setIndex(scaledIndex,
|
|
||||||
getDeviceForStream(streamType));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
mIndex.put(device, index);
|
||||||
} else {
|
|
||||||
return false;
|
if (oldIndex != index) {
|
||||||
|
// 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].setIndex(scaledIndex,
|
||||||
|
device);
|
||||||
|
if (currentDevice) {
|
||||||
|
mStreamStates[streamType].setIndex(scaledIndex,
|
||||||
|
getDeviceForStream(streamType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getIndex(int device) {
|
public int getIndex(int device) {
|
||||||
Integer index = mIndex.get(device);
|
synchronized (VolumeStreamState.class) {
|
||||||
if (index == null) {
|
Integer index = mIndex.get(device);
|
||||||
// there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
|
if (index == null) {
|
||||||
index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT);
|
// there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
|
||||||
|
index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT);
|
||||||
|
}
|
||||||
|
return index.intValue();
|
||||||
}
|
}
|
||||||
return index.intValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxIndex() {
|
public int getMaxIndex() {
|
||||||
return mIndexMax;
|
return mIndexMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setAllIndexes(VolumeStreamState srcStream) {
|
public void setAllIndexes(VolumeStreamState srcStream) {
|
||||||
int srcStreamType = srcStream.getStreamType();
|
synchronized (VolumeStreamState.class) {
|
||||||
// apply default device volume from source stream to all devices first in case
|
int srcStreamType = srcStream.getStreamType();
|
||||||
// some devices are present in this stream state but not in source stream state
|
// apply default device volume from source stream to all devices first in case
|
||||||
int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
|
// some devices are present in this stream state but not in source stream state
|
||||||
index = rescaleIndex(index, srcStreamType, mStreamType);
|
int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
|
||||||
Set set = mIndex.entrySet();
|
|
||||||
Iterator i = set.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
Map.Entry entry = (Map.Entry)i.next();
|
|
||||||
entry.setValue(index);
|
|
||||||
}
|
|
||||||
// Now apply actual volume for devices in source stream state
|
|
||||||
set = srcStream.mIndex.entrySet();
|
|
||||||
i = set.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
Map.Entry entry = (Map.Entry)i.next();
|
|
||||||
int device = ((Integer)entry.getKey()).intValue();
|
|
||||||
index = ((Integer)entry.getValue()).intValue();
|
|
||||||
index = rescaleIndex(index, srcStreamType, mStreamType);
|
index = rescaleIndex(index, srcStreamType, mStreamType);
|
||||||
|
Set set = mIndex.entrySet();
|
||||||
|
Iterator i = set.iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
Map.Entry entry = (Map.Entry)i.next();
|
||||||
|
entry.setValue(index);
|
||||||
|
}
|
||||||
|
// Now apply actual volume for devices in source stream state
|
||||||
|
set = srcStream.mIndex.entrySet();
|
||||||
|
i = set.iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
Map.Entry entry = (Map.Entry)i.next();
|
||||||
|
int device = ((Integer)entry.getKey()).intValue();
|
||||||
|
index = ((Integer)entry.getValue()).intValue();
|
||||||
|
index = rescaleIndex(index, srcStreamType, mStreamType);
|
||||||
|
|
||||||
setIndex(index, device);
|
setIndex(index, device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setAllIndexesToMax() {
|
public void setAllIndexesToMax() {
|
||||||
Set set = mIndex.entrySet();
|
synchronized (VolumeStreamState.class) {
|
||||||
Iterator i = set.iterator();
|
Set set = mIndex.entrySet();
|
||||||
while (i.hasNext()) {
|
Iterator i = set.iterator();
|
||||||
Map.Entry entry = (Map.Entry)i.next();
|
while (i.hasNext()) {
|
||||||
entry.setValue(mIndexMax);
|
Map.Entry entry = (Map.Entry)i.next();
|
||||||
|
entry.setValue(mIndexMax);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void mute(IBinder cb, boolean state) {
|
public void mute(IBinder cb, boolean state) {
|
||||||
VolumeDeathHandler handler = getDeathHandler(cb, state);
|
synchronized (VolumeStreamState.class) {
|
||||||
if (handler == null) {
|
VolumeDeathHandler handler = getDeathHandler(cb, state);
|
||||||
Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
|
if (handler == null) {
|
||||||
return;
|
Log.e(TAG, "Could not get client death handler for stream: "+mStreamType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handler.mute(state);
|
||||||
}
|
}
|
||||||
handler.mute(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getStreamType() {
|
public int getStreamType() {
|
||||||
|
|||||||
Reference in New Issue
Block a user