[BUG] AudioService: fix mute/umute of aliased streams.
Mute/umute of aliased streams is asymetric according to activation/ de-activation mute events. A toggle mute will mute/unmute all aliased whereas a togglemute/raise will mute all aliased and unmute only the concerned stream of the raise event. A toggle mute and a setStreamVolume will mute all aliased and unmute only the concercend stream of the setVolume request. This CL makes the behavior homogeneous for aliased stream among all activation/deactivation mute events. Test: adb shell am instrument -w com.android.audiopolicytest com.android.audiopolicytest Bug: 260298113 Signed-off-by: François Gaffie <francois.gaffie@renault.com> Change-Id: I803f9df1c30755b8b5530c4b373c79ea4efd5010 Merged-In: I803f9df1c30755b8b5530c4b373c79ea4efd5010
This commit is contained in:
committed by
Eric Laurent
parent
c8e375e0a3
commit
92a2d9aa7f
@@ -3340,15 +3340,7 @@ public class AudioService extends IAudioService.Stub
|
||||
} else {
|
||||
state = direction == AudioManager.ADJUST_MUTE;
|
||||
}
|
||||
for (int stream = 0; stream < mStreamStates.length; stream++) {
|
||||
if (streamTypeAlias == mStreamVolumeAlias[stream]) {
|
||||
if (!(readCameraSoundForced()
|
||||
&& (mStreamStates[stream].getStreamType()
|
||||
== AudioSystem.STREAM_SYSTEM_ENFORCED))) {
|
||||
mStreamStates[stream].mute(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
muteAliasStreams(streamTypeAlias, state);
|
||||
} else if ((direction == AudioManager.ADJUST_RAISE) &&
|
||||
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
|
||||
Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
|
||||
@@ -3363,7 +3355,7 @@ public class AudioService extends IAudioService.Stub
|
||||
// Unmute the stream if it was previously muted
|
||||
if (direction == AudioManager.ADJUST_RAISE) {
|
||||
// unmute immediately for volume up
|
||||
streamState.mute(false);
|
||||
muteAliasStreams(streamTypeAlias, false);
|
||||
} else if (direction == AudioManager.ADJUST_LOWER) {
|
||||
if (mIsSingleVolume) {
|
||||
sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
|
||||
@@ -3489,6 +3481,42 @@ public class AudioService extends IAudioService.Stub
|
||||
sendVolumeUpdate(streamType, oldIndex, newIndex, flags, device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops on aliasted stream, update the mute cache attribute of each
|
||||
* {@see AudioService#VolumeStreamState}, and then apply the change.
|
||||
* It prevents to unnecessary {@see AudioSystem#setStreamVolume} done for each stream
|
||||
* and aliases before mute change changed and after.
|
||||
*/
|
||||
private void muteAliasStreams(int streamAlias, boolean state) {
|
||||
synchronized (VolumeStreamState.class) {
|
||||
List<Integer> streamsToMute = new ArrayList<>();
|
||||
for (int stream = 0; stream < mStreamStates.length; stream++) {
|
||||
if (streamAlias == mStreamVolumeAlias[stream]) {
|
||||
if (!(readCameraSoundForced()
|
||||
&& (mStreamStates[stream].getStreamType()
|
||||
== AudioSystem.STREAM_SYSTEM_ENFORCED))) {
|
||||
boolean changed = mStreamStates[stream].mute(state, /* apply= */ false);
|
||||
if (changed) {
|
||||
streamsToMute.add(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
streamsToMute.forEach(streamToMute -> {
|
||||
mStreamStates[streamToMute].doMute();
|
||||
broadcastMuteSetting(streamToMute, state);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastMuteSetting(int streamType, boolean isMuted) {
|
||||
// Stream mute changed, fire the intent.
|
||||
Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
|
||||
intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType);
|
||||
intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, isMuted);
|
||||
sendBroadcastToAll(intent);
|
||||
}
|
||||
|
||||
// Called after a delay when volume down is pressed while muted
|
||||
private void onUnmuteStream(int stream, int flags) {
|
||||
boolean wasMuted;
|
||||
@@ -3608,7 +3636,8 @@ public class AudioService extends IAudioService.Stub
|
||||
// except for BT SCO stream where only explicit mute is allowed to comply to BT requirements
|
||||
if ((streamType != AudioSystem.STREAM_BLUETOOTH_SCO)
|
||||
&& (getDeviceForStream(stream) == device)) {
|
||||
mStreamStates[stream].mute(index == 0);
|
||||
// As adjustStreamVolume with muteAdjust flags mute/unmutes stream and aliased streams.
|
||||
muteAliasStreams(stream, index == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7866,8 +7895,8 @@ public class AudioService extends IAudioService.Stub
|
||||
private int mIndexMinNoPerm;
|
||||
private int mIndexMax;
|
||||
|
||||
private boolean mIsMuted;
|
||||
private boolean mIsMutedInternally;
|
||||
private boolean mIsMuted = false;
|
||||
private boolean mIsMutedInternally = false;
|
||||
private String mVolumeIndexSettingName;
|
||||
@NonNull private Set<Integer> mObservedDeviceSet = new TreeSet<>();
|
||||
|
||||
@@ -8292,27 +8321,10 @@ public class AudioService extends IAudioService.Stub
|
||||
public boolean mute(boolean state) {
|
||||
boolean changed = false;
|
||||
synchronized (VolumeStreamState.class) {
|
||||
if (state != mIsMuted) {
|
||||
changed = true;
|
||||
mIsMuted = state;
|
||||
|
||||
// Set the new mute volume. This propagates the values to
|
||||
// the audio system, otherwise the volume won't be changed
|
||||
// at the lower level.
|
||||
sendMsg(mAudioHandler,
|
||||
MSG_SET_ALL_VOLUMES,
|
||||
SENDMSG_QUEUE,
|
||||
0,
|
||||
0,
|
||||
this, 0);
|
||||
}
|
||||
changed = mute(state, true);
|
||||
}
|
||||
if (changed) {
|
||||
// Stream mute changed, fire the intent.
|
||||
Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
|
||||
intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
|
||||
intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
|
||||
sendBroadcastToAll(intent);
|
||||
broadcastMuteSetting(mStreamType, state);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
@@ -8344,6 +8356,41 @@ public class AudioService extends IAudioService.Stub
|
||||
return mIsMuted || mIsMutedInternally;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mute/unmute the stream
|
||||
* @param state the new mute state
|
||||
* @param apply true to propagate to HW, or false just to update the cache. May be needed
|
||||
* to mute a stream and its aliases as applyAllVolume will force settings to aliases.
|
||||
* It prevents unnecessary calls to {@see AudioSystem#setStreamVolume}
|
||||
* @return true if the mute state was changed
|
||||
*/
|
||||
public boolean mute(boolean state, boolean apply) {
|
||||
synchronized (VolumeStreamState.class) {
|
||||
boolean changed = state != mIsMuted;
|
||||
if (changed) {
|
||||
mIsMuted = state;
|
||||
if (apply) {
|
||||
doMute();
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
public void doMute() {
|
||||
synchronized (VolumeStreamState.class) {
|
||||
// Set the new mute volume. This propagates the values to
|
||||
// the audio system, otherwise the volume won't be changed
|
||||
// at the lower level.
|
||||
sendMsg(mAudioHandler,
|
||||
MSG_SET_ALL_VOLUMES,
|
||||
SENDMSG_QUEUE,
|
||||
0,
|
||||
0,
|
||||
this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int getStreamType() {
|
||||
return mStreamType;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user