Expose getAudioDevicesForAttributes

Allow all apps to query the audio device output(s) for an AudioTrack
with defined AudioAttributes.
Provide an alternative path (AudioService#getDevicesForAttributesUnprotected)
to query this similar with the existing gated SystemApi.

Test: atest android.media.audio.cts.AudioDevicesForAttributesTest
Bug: 190810951
Change-Id: Id8bfcf809f42bd5500d59b96a2595a1b8b0d855b
This commit is contained in:
Dorin Drimus
2021-12-22 11:46:26 +01:00
parent 9a42318fcd
commit daeb6a944a
4 changed files with 51 additions and 0 deletions

View File

@@ -20955,6 +20955,7 @@ package android.media {
method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
method public int getAllowedCapturePolicy();
method @NonNull public java.util.List<android.media.AudioDeviceInfo> getAudioDevicesForAttributes(@NonNull android.media.AudioAttributes);
method public int getAudioHwSyncForSession(int);
method @NonNull public java.util.List<android.media.AudioDeviceInfo> getAvailableCommunicationDevices();
method @Nullable public android.media.AudioDeviceInfo getCommunicationDevice();

View File

@@ -79,6 +79,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -5665,6 +5666,43 @@ public class AudioManager {
}
}
/**
* Get the audio devices that would be used for the routing of the given audio attributes.
* These are the devices anticipated to play sound from an {@link AudioTrack} created with
* the specified {@link AudioAttributes}.
* The audio routing can change if audio devices are physically connected or disconnected or
* concurrently through {@link AudioRouting} or {@link MediaRouter}.
* @param attributes the {@link AudioAttributes} for which the routing is being queried
* @return an empty list if there was an issue with the request, a list of
* {@link AudioDeviceInfo} otherwise (typically one device, except for duplicated paths).
*/
public @NonNull List<AudioDeviceInfo> getAudioDevicesForAttributes(
@NonNull AudioAttributes attributes) {
final List<AudioDeviceAttributes> devicesForAttributes;
try {
Objects.requireNonNull(attributes);
final IAudioService service = getService();
devicesForAttributes = service.getDevicesForAttributesUnprotected(attributes);
} catch (Exception e) {
Log.i(TAG, "No audio devices available for specified attributes.");
return Collections.emptyList();
}
// Map from AudioDeviceAttributes to AudioDeviceInfo
AudioDeviceInfo[] outputDeviceInfos = getDevicesStatic(GET_DEVICES_OUTPUTS);
List<AudioDeviceInfo> deviceInfosForAttributes = new ArrayList<>();
for (AudioDeviceAttributes deviceForAttributes : devicesForAttributes) {
for (AudioDeviceInfo deviceInfo : outputDeviceInfos) {
if (deviceForAttributes.getType() == deviceInfo.getType()
&& TextUtils.equals(deviceForAttributes.getAddress(),
deviceInfo.getAddress())) {
deviceInfosForAttributes.add(deviceInfo);
}
}
}
return Collections.unmodifiableList(deviceInfosForAttributes);
}
/**
* @hide
* Volume behavior for an audio device that has no particular volume behavior set. Invalid as

View File

@@ -308,6 +308,8 @@ interface IAudioService {
List<AudioDeviceAttributes> getDevicesForAttributes(in AudioAttributes attributes);
List<AudioDeviceAttributes> getDevicesForAttributesUnprotected(in AudioAttributes attributes);
int setAllowedCapturePolicy(in int capturePolicy);
int getAllowedCapturePolicy();

View File

@@ -2611,6 +2611,16 @@ public class AudioService extends IAudioService.Stub
return getDevicesForAttributesInt(attributes);
}
/** @see AudioManager#getAudioDevicesForAttributes(AudioAttributes)
* This method is similar with AudioService#getDevicesForAttributes,
* only it doesn't enforce permissions because it is used by an unprivileged public API
* instead of the system API.
*/
public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesUnprotected(
@NonNull AudioAttributes attributes) {
return getDevicesForAttributesInt(attributes);
}
/**
* @see AudioManager#isMusicActive()
* @param remotely true if query is for remote playback (cast), false for local playback.