[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 <francois.gaffie@renault.com>
Change-Id: I2aaf64fbe0c0fac3bb0110d847453eaf34f80792
Merged-In: I2aaf64fbe0c0fac3bb0110d847453eaf34f80792
This commit is contained in:
Francois Gaffie
2021-11-10 13:12:18 +01:00
committed by Eric Laurent
parent 2953bacfde
commit e90ba65e60
2 changed files with 51 additions and 39 deletions

View File

@@ -29,10 +29,10 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* @hide * @hide
@@ -142,7 +142,7 @@ public final class AudioProductStrategy implements Parcelable {
*/ */
public static int getLegacyStreamTypeForStrategyWithAudioAttributes( public static int getLegacyStreamTypeForStrategyWithAudioAttributes(
@NonNull AudioAttributes audioAttributes) { @NonNull AudioAttributes audioAttributes) {
Preconditions.checkNotNull(audioAttributes, "AudioAttributes must not be null"); Objects.requireNonNull(audioAttributes, "AudioAttributes must not be null");
for (final AudioProductStrategy productStrategy : for (final AudioProductStrategy productStrategy :
AudioProductStrategy.getAudioProductStrategies()) { AudioProductStrategy.getAudioProductStrategies()) {
if (productStrategy.supportsAudioAttributes(audioAttributes)) { if (productStrategy.supportsAudioAttributes(audioAttributes)) {
@@ -162,6 +162,30 @@ public final class AudioProductStrategy implements Parcelable {
return AudioSystem.STREAM_MUSIC; 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
* <p>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<AudioProductStrategy> initializeAudioProductStrategies() { private static List<AudioProductStrategy> initializeAudioProductStrategies() {
ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>(); ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
int status = native_list_audio_product_strategies(apsList); int status = native_list_audio_product_strategies(apsList);
@@ -192,8 +216,8 @@ public final class AudioProductStrategy implements Parcelable {
*/ */
private AudioProductStrategy(@NonNull String name, int id, private AudioProductStrategy(@NonNull String name, int id,
@NonNull AudioAttributesGroup[] aag) { @NonNull AudioAttributesGroup[] aag) {
Preconditions.checkNotNull(name, "name must not be null"); Objects.requireNonNull(name, "name must not be null");
Preconditions.checkNotNull(aag, "AudioAttributesGroups must not be null"); Objects.requireNonNull(aag, "AudioAttributesGroups must not be null");
mName = name; mName = name;
mId = id; mId = id;
mAudioAttributesGroups = aag; mAudioAttributesGroups = aag;
@@ -243,7 +267,7 @@ public final class AudioProductStrategy implements Parcelable {
*/ */
@TestApi @TestApi
public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) { 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) { for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
if (aag.supportsAttributes(aa)) { if (aag.supportsAttributes(aa)) {
return aag.getStreamType(); return aag.getStreamType();
@@ -260,7 +284,7 @@ public final class AudioProductStrategy implements Parcelable {
*/ */
@SystemApi @SystemApi
public boolean supportsAudioAttributes(@NonNull AudioAttributes aa) { 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) { for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
if (aag.supportsAttributes(aa)) { if (aag.supportsAttributes(aa)) {
return true; return true;
@@ -293,7 +317,7 @@ public final class AudioProductStrategy implements Parcelable {
*/ */
@TestApi @TestApi
public int getVolumeGroupIdForAudioAttributes(@NonNull AudioAttributes aa) { 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) { for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
if (aag.supportsAttributes(aa)) { if (aag.supportsAttributes(aa)) {
return aag.getVolumeGroupId(); return aag.getVolumeGroupId();
@@ -302,6 +326,17 @@ public final class AudioProductStrategy implements Parcelable {
return AudioVolumeGroup.DEFAULT_VOLUME_GROUP; 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 @Override
public int describeContents() { public int describeContents() {
return 0; return 0;
@@ -377,8 +412,8 @@ public final class AudioProductStrategy implements Parcelable {
*/ */
private static boolean attributesMatches(@NonNull AudioAttributes refAttr, private static boolean attributesMatches(@NonNull AudioAttributes refAttr,
@NonNull AudioAttributes attr) { @NonNull AudioAttributes attr) {
Preconditions.checkNotNull(refAttr, "refAttr must not be null"); Objects.requireNonNull(refAttr, "reference AudioAttributes must not be null");
Preconditions.checkNotNull(attr, "attr must not be null"); Objects.requireNonNull(attr, "requester's AudioAttributes must not be null");
String refFormattedTags = TextUtils.join(";", refAttr.getTags()); String refFormattedTags = TextUtils.join(";", refAttr.getTags());
String cliFormattedTags = TextUtils.join(";", attr.getTags()); String cliFormattedTags = TextUtils.join(";", attr.getTags());
if (refAttr.equals(DEFAULT_ATTRIBUTES)) { if (refAttr.equals(DEFAULT_ATTRIBUTES)) {

View File

@@ -3669,12 +3669,13 @@ public class AudioService extends IAudioService.Stub
String callingPackage, String attributionTag) { String callingPackage, String attributionTag) {
enforceModifyAudioRoutingPermission(); enforceModifyAudioRoutingPermission();
Objects.requireNonNull(attr, "attr must not be null"); 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) { if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
Log.e(TAG, ": no volume group found for attributes " + attr.toString()); Log.e(TAG, ": no volume group found for attributes " + attr.toString());
return; return;
} }
final VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup); VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_GROUP_VOL, attr, vgs.name(), sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_GROUP_VOL, attr, vgs.name(),
index/*val1*/, flags/*val2*/, callingPackage)); index/*val1*/, flags/*val2*/, callingPackage));
@@ -3682,7 +3683,7 @@ public class AudioService extends IAudioService.Stub
vgs.setVolumeIndex(index, flags); vgs.setVolumeIndex(index, flags);
// For legacy reason, propagate to all streams associated to this volume group // For legacy reason, propagate to all streams associated to this volume group
for (final int groupedStream : vgs.getLegacyStreamTypes()) { for (int groupedStream : vgs.getLegacyStreamTypes()) {
try { try {
ensureValidStreamType(groupedStream); ensureValidStreamType(groupedStream);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@@ -3712,7 +3713,9 @@ public class AudioService extends IAudioService.Stub
public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) { public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
enforceModifyAudioRoutingPermission(); enforceModifyAudioRoutingPermission();
Objects.requireNonNull(attr, "attr must not be null"); 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) { if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
throw new IllegalArgumentException("No volume group for attributes " + attr); throw new IllegalArgumentException("No volume group for attributes " + attr);
} }
@@ -4264,31 +4267,6 @@ public class AudioService extends IAudioService.Stub
} }
} }
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, private void dispatchAbsoluteVolumeChanged(int streamType, AbsoluteVolumeDeviceInfo deviceInfo,
int index) { int index) {
VolumeInfo volumeInfo = deviceInfo.getMatchingVolumeInfoForStream(streamType); VolumeInfo volumeInfo = deviceInfo.getMatchingVolumeInfoForStream(streamType);
@@ -4321,7 +4299,6 @@ public class AudioService extends IAudioService.Stub
} }
} }
// No ringer or zen muted stream volumes can be changed unless it'll exit dnd // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) { private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
switch (mNm.getZenMode()) { switch (mNm.getZenMode()) {