diff options
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 111 |
1 files changed, 79 insertions, 32 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d0ad7cd5b351..af96829fd2ab 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -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; } |