summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Francois Gaffie <francois.gaffie@renault.com> 2021-11-10 13:48:42 +0100
committer Eric Laurent <elaurent@google.com> 2023-01-27 14:16:45 +0000
commit31bb5135ccdc23e4950fdcc1f7701154c7044ca0 (patch)
tree26f97b9bad5a39fa807f42586cf9916f24f7aca9
parent92a2d9aa7f0ef31f7dbd0ffe7e0bbf50f3d958d7 (diff)
[IMPR] AudioService: improve bijectivity between VSS / VGS
Bug: 260298113 This CL improves bijectivity between VolumeStreamStates and VolumeGroupStates. The cache of the stream/attributes volume must by synced on not only the values but also the muted state. To prevent race, VSS and VGS are synchronized on the same lock as they need to sync each others. Test: dumpsys audio & check index aligned between stream and associated volume group adb shell am instrument -w -e class com.android.audiopolicytest.* com.android.audiopolicytest Signed-off-by: Francois Gaffie <francois.gaffie@renault.com> Change-Id: I78bfa0d1d87d90125f101bdb77e504181cc4c77e Merged-In: I78bfa0d1d87d90125f101bdb77e504181cc4c77e
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java84
1 files changed, 84 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index af96829fd2ab..e1d7d56f041e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1253,6 +1253,20 @@ public class AudioService extends IAudioService.Stub
0 /* arg1 */, 0 /* arg2 */, null /* obj */, 0 /* delay */);
}
+ private void initVolumeStreamStates() {
+ int numStreamTypes = AudioSystem.getNumStreamTypes();
+ synchronized (VolumeStreamState.class) {
+ for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+ VolumeStreamState streamState = mStreamStates[streamType];
+ int groupId = getVolumeGroupForStreamType(streamType);
+ if (groupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP
+ && sVolumeGroupStates.indexOfKey(groupId) >= 0) {
+ streamState.setVolumeGroupState(sVolumeGroupStates.get(groupId));
+ }
+ }
+ }
+ }
+
/**
* Separating notification volume from ring is NOT of aliasing the corresponding streams
* @param properties
@@ -1282,6 +1296,8 @@ public class AudioService extends IAudioService.Stub
// mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
// relies on audio policy having correct ranges for volume indexes.
mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+ // Link VGS on VSS
+ initVolumeStreamStates();
// Call setRingerModeInt() to apply correct mute
// state on streams affected by ringer mode.
@@ -3854,6 +3870,23 @@ public class AudioService extends IAudioService.Stub
return;
}
VolumeGroupState vgs = sVolumeGroupStates.get(groupId);
+ // For compatibility reason, use stream API if group linked to a valid stream
+ for (int stream : vgs.getLegacyStreamTypes()) {
+ try {
+ ensureValidStreamType(stream);
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "volume group " + groupId + " has internal streams (" + stream
+ + "), do not change associated stream volume");
+ continue;
+ }
+ // Call only for the first valid stream, legacy API will propagate to aliased streams.
+ // Note: Group and Stream does not share same convention, 0 is mute for stream,
+ // min index is acting as mute for Groups
+ if (vgs.isVssMuteBijective(stream)) {
+ adjustStreamVolume(stream, direction, flags, callingPackage);
+ return;
+ }
+ }
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_GROUP_VOL, vgs.name(),
direction, flags, callingPackage));
vgs.adjustVolume(direction, flags);
@@ -7432,6 +7465,16 @@ public class AudioService extends IAudioService.Stub
|| stream == AudioSystem.STREAM_BLUETOOTH_SCO;
}
+ private static int getVolumeGroupForStreamType(int stream) {
+ AudioAttributes attributes =
+ AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(stream);
+ if (attributes.equals(new AudioAttributes.Builder().build())) {
+ return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
+ }
+ return AudioProductStrategy.getVolumeGroupIdForAudioAttributes(
+ attributes, /* fallbackOnDefault= */ false);
+ }
+
// NOTE: Locking order for synchronized objects related to volume management:
// 1 mSettingsLock
// 2 VolumeStreamState.class
@@ -7890,6 +7933,7 @@ public class AudioService extends IAudioService.Stub
// 4 VolumeStreamState.class
private class VolumeStreamState {
private final int mStreamType;
+ private VolumeGroupState mVolumeGroupState = null;
private int mIndexMin;
// min index when user doesn't have permission to change audio settings
private int mIndexMinNoPerm;
@@ -7954,6 +7998,15 @@ public class AudioService extends IAudioService.Stub
}
/**
+ * Associate a {@link volumeGroupState} on the {@link VolumeStreamState}.
+ * <p> It helps to synchronize the index, mute attributes on the maching
+ * {@link volumeGroupState}
+ * @param volumeGroupState matching the {@link VolumeStreamState}
+ */
+ public void setVolumeGroupState(VolumeGroupState volumeGroupState) {
+ mVolumeGroupState = volumeGroupState;
+ }
+ /**
* Update the minimum index that can be used without MODIFY_AUDIO_SETTINGS permission
* @param index minimum index expressed in "UI units", i.e. no 10x factor
*/
@@ -8211,6 +8264,9 @@ public class AudioService extends IAudioService.Stub
}
}
if (changed) {
+ // If associated to volume group, update group cache
+ updateVolumeGroupIndex(device, /* forceMuteState= */ false);
+
oldIndex = (oldIndex + 5) / 10;
index = (index + 5) / 10;
// log base stream changes to the event log
@@ -8313,6 +8369,28 @@ public class AudioService extends IAudioService.Stub
}
}
+ // If associated to volume group, update group cache
+ private void updateVolumeGroupIndex(int device, boolean forceMuteState) {
+ synchronized (VolumeStreamState.class) {
+ if (mVolumeGroupState != null) {
+ int groupIndex = (getIndex(device) + 5) / 10;
+ if (DEBUG_VOL) {
+ Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
+ + ", muted=" + mIsMuted + ", device=" + device + ", index="
+ + getIndex(device) + ", group " + mVolumeGroupState.name()
+ + " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex
+ + ", forceMuteState=" + forceMuteState);
+ }
+ mVolumeGroupState.updateVolumeIndex(groupIndex, device);
+ // Only propage mute of stream when applicable
+ if (mIndexMin == 0 || isCallStream(mStreamType)) {
+ // For call stream, align mute only when muted, not when index is set to 0
+ mVolumeGroupState.mute(forceMuteState ? mIsMuted : groupIndex == 0);
+ }
+ }
+ }
+ }
+
/**
* Mute/unmute the stream
* @param state the new mute state
@@ -8379,6 +8457,9 @@ public class AudioService extends IAudioService.Stub
public void doMute() {
synchronized (VolumeStreamState.class) {
+ // If associated to volume group, update group cache
+ updateVolumeGroupIndex(getDeviceForStream(mStreamType), /* forceMuteState= */ true);
+
// Set the new mute volume. This propagates the values to
// the audio system, otherwise the volume won't be changed
// at the lower level.
@@ -8460,6 +8541,9 @@ public class AudioService extends IAudioService.Stub
pw.println();
pw.print(" Devices: ");
pw.print(AudioSystem.deviceSetToString(getDeviceSetForStream(mStreamType)));
+ pw.println();
+ pw.print(" Volume Group: ");
+ pw.println(mVolumeGroupState != null ? mVolumeGroupState.name() : "n/a");
}
}