[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:
committed by
Eric Laurent
parent
2953bacfde
commit
e90ba65e60
@@ -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)) {
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user