From 34ded2e8b1297a8865f1b00feb262c57475c8430 Mon Sep 17 00:00:00 2001 From: Francois Gaffie Date: Wed, 10 Nov 2021 13:12:18 +0100 Subject: [PATCH] [IMPR] AudioProductStrategy: get volume group from AudioAttributes This CL adds an API to find a volume group from a given audio attributes. It allows to fallback or not on default volume group. Bug: 260298113 Test: adb shell am instrument -w -e class com.android.audiopolicytest.AudioManagerTest com.android.audiopolicytest adb shell am instrument -w -e class com.android.audiopolicytest.AudioProductStrategyTest com.android.audiopolicytest adb shell am instrument -w -e class com.android.audiopolicytest.AudioVolumeGroupTest com.android.audiopolicytest adb shell am instrument -w -e class com.android.audiopolicytest.AudioVolumeGroupChangeHandlerTest com.android.audiopolicytest Signed-off-by: Francois Gaffie Change-Id: I2aaf64fbe0c0fac3bb0110d847453eaf34f80792 --- .../audiopolicy/AudioProductStrategy.java | 53 +++++++++++++++---- .../android/server/audio/AudioService.java | 37 +++---------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java index 98819a3582a67..0198419984303 100644 --- a/media/java/android/media/audiopolicy/AudioProductStrategy.java +++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java @@ -28,11 +28,11 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; /** * @hide @@ -140,7 +140,7 @@ public final class AudioProductStrategy implements Parcelable { */ public static int getLegacyStreamTypeForStrategyWithAudioAttributes( @NonNull AudioAttributes audioAttributes) { - Preconditions.checkNotNull(audioAttributes, "AudioAttributes must not be null"); + Objects.requireNonNull(audioAttributes, "AudioAttributes must not be null"); for (final AudioProductStrategy productStrategy : AudioProductStrategy.getAudioProductStrategies()) { if (productStrategy.supportsAudioAttributes(audioAttributes)) { @@ -160,6 +160,30 @@ public final class AudioProductStrategy implements Parcelable { return AudioSystem.STREAM_MUSIC; } + /** + * @hide + * @param attributes the {@link AudioAttributes} to identify VolumeGroupId with + * @param fallbackOnDefault if set, allows to fallback on the default group (e.g. the group + * associated to {@link AudioManager#STREAM_MUSIC}). + * @return volume group id associated with the given {@link AudioAttributes} if found, + * default volume group id if fallbackOnDefault is set + *

By convention, the product strategy with default attributes will be associated to the + * default volume group (e.g. associated to {@link AudioManager#STREAM_MUSIC}) + * or {@link AudioVolumeGroup#DEFAULT_VOLUME_GROUP} if not found. + */ + public static int getVolumeGroupIdForAudioAttributes( + @NonNull AudioAttributes attributes, boolean fallbackOnDefault) { + Objects.requireNonNull(attributes, "attributes must not be null"); + int volumeGroupId = getVolumeGroupIdForAudioAttributesInt(attributes); + if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + if (fallbackOnDefault) { + return getVolumeGroupIdForAudioAttributesInt(getDefaultAttributes()); + } + return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; + } + private static List initializeAudioProductStrategies() { ArrayList apsList = new ArrayList(); int status = native_list_audio_product_strategies(apsList); @@ -190,8 +214,8 @@ public final class AudioProductStrategy implements Parcelable { */ private AudioProductStrategy(@NonNull String name, int id, @NonNull AudioAttributesGroup[] aag) { - Preconditions.checkNotNull(name, "name must not be null"); - Preconditions.checkNotNull(aag, "AudioAttributesGroups must not be null"); + Objects.requireNonNull(name, "name must not be null"); + Objects.requireNonNull(aag, "AudioAttributesGroups must not be null"); mName = name; mId = id; mAudioAttributesGroups = aag; @@ -241,7 +265,7 @@ public final class AudioProductStrategy implements Parcelable { */ @TestApi public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) { - Preconditions.checkNotNull(aa, "AudioAttributes must not be null"); + Objects.requireNonNull(aa, "AudioAttributes must not be null"); for (final AudioAttributesGroup aag : mAudioAttributesGroups) { if (aag.supportsAttributes(aa)) { return aag.getStreamType(); @@ -258,7 +282,7 @@ public final class AudioProductStrategy implements Parcelable { */ @SystemApi public boolean supportsAudioAttributes(@NonNull AudioAttributes aa) { - Preconditions.checkNotNull(aa, "AudioAttributes must not be null"); + Objects.requireNonNull(aa, "AudioAttributes must not be null"); for (final AudioAttributesGroup aag : mAudioAttributesGroups) { if (aag.supportsAttributes(aa)) { return true; @@ -291,7 +315,7 @@ public final class AudioProductStrategy implements Parcelable { */ @TestApi public int getVolumeGroupIdForAudioAttributes(@NonNull AudioAttributes aa) { - Preconditions.checkNotNull(aa, "AudioAttributes must not be null"); + Objects.requireNonNull(aa, "AudioAttributes must not be null"); for (final AudioAttributesGroup aag : mAudioAttributesGroups) { if (aag.supportsAttributes(aa)) { return aag.getVolumeGroupId(); @@ -300,6 +324,17 @@ public final class AudioProductStrategy implements Parcelable { return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; } + private static int getVolumeGroupIdForAudioAttributesInt(@NonNull AudioAttributes attributes) { + Objects.requireNonNull(attributes, "attributes must not be null"); + for (AudioProductStrategy productStrategy : getAudioProductStrategies()) { + int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes); + if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { + return volumeGroupId; + } + } + return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; + } + @Override public int describeContents() { return 0; @@ -374,8 +409,8 @@ public final class AudioProductStrategy implements Parcelable { */ private static boolean attributesMatches(@NonNull AudioAttributes refAttr, @NonNull AudioAttributes attr) { - Preconditions.checkNotNull(refAttr, "refAttr must not be null"); - Preconditions.checkNotNull(attr, "attr must not be null"); + Objects.requireNonNull(refAttr, "reference AudioAttributes must not be null"); + Objects.requireNonNull(attr, "requester's AudioAttributes must not be null"); String refFormattedTags = TextUtils.join(";", refAttr.getTags()); String cliFormattedTags = TextUtils.join(";", attr.getTags()); if (refAttr.equals(DEFAULT_ATTRIBUTES)) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 58ddd9c6a8b81..39c7f30174703 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3785,12 +3785,13 @@ public class AudioService extends IAudioService.Stub super.setVolumeIndexForAttributes_enforcePermission(); Objects.requireNonNull(attr, "attr must not be null"); - final int volumeGroup = getVolumeGroupIdForAttributes(attr); + int volumeGroup = AudioProductStrategy.getVolumeGroupIdForAudioAttributes( + attr, /* fallbackOnDefault= */false); if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) { Log.e(TAG, ": no volume group found for attributes " + attr.toString()); return; } - final VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup); + VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup); sVolumeLogger.enqueue(new VolumeEvent(VolumeEvent.VOL_SET_GROUP_VOL, attr, vgs.name(), index/*val1*/, flags/*val2*/, callingPackage)); @@ -3798,7 +3799,7 @@ public class AudioService extends IAudioService.Stub vgs.setVolumeIndex(index, flags); // For legacy reason, propagate to all streams associated to this volume group - for (final int groupedStream : vgs.getLegacyStreamTypes()) { + for (int groupedStream : vgs.getLegacyStreamTypes()) { try { ensureValidStreamType(groupedStream); } catch (IllegalArgumentException e) { @@ -3830,7 +3831,9 @@ public class AudioService extends IAudioService.Stub super.getVolumeIndexForAttributes_enforcePermission(); Objects.requireNonNull(attr, "attr must not be null"); - final int volumeGroup = getVolumeGroupIdForAttributes(attr); + final int volumeGroup = + AudioProductStrategy.getVolumeGroupIdForAudioAttributes( + attr, /* fallbackOnDefault= */false); if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) { throw new IllegalArgumentException("No volume group for attributes " + attr); } @@ -4380,31 +4383,6 @@ public class AudioService extends IAudioService.Stub sendVolumeUpdate(streamType, oldIndex, index, flags, device); } - - - private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) { - Objects.requireNonNull(attributes, "attributes must not be null"); - int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes); - if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { - return volumeGroupId; - } - // The default volume group is the one hosted by default product strategy, i.e. - // supporting Default Attributes - return getVolumeGroupIdForAttributesInt(AudioProductStrategy.getDefaultAttributes()); - } - - private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) { - Objects.requireNonNull(attributes, "attributes must not be null"); - for (final AudioProductStrategy productStrategy : - AudioProductStrategy.getAudioProductStrategies()) { - int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes); - if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { - return volumeGroupId; - } - } - return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; - } - private void dispatchAbsoluteVolumeChanged(int streamType, AbsoluteVolumeDeviceInfo deviceInfo, int index) { VolumeInfo volumeInfo = deviceInfo.getMatchingVolumeInfoForStream(streamType); @@ -4437,7 +4415,6 @@ public class AudioService extends IAudioService.Stub } } - // No ringer or zen muted stream volumes can be changed unless it'll exit dnd private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) { switch (mNm.getZenMode()) {