Add API for querying direct playback support.

Add API for querying direct playback support. Direct playback can be
compressed offload playback or direct bistream playback. This API
can help developers to discover device's capabilities.

Bug: 197838445
Test: atest AudioManagerTest
Change-Id: I1c04e6595c12559e17b3d68155b2d0e7d0909421
This commit is contained in:
jiabin
2021-12-10 01:09:02 +00:00
parent 7d148d1b40
commit e22f6aa613
6 changed files with 155 additions and 7 deletions

View File

@@ -20749,11 +20749,12 @@ package android.media {
method @NonNull public java.util.List<android.media.AudioDeviceInfo> getAvailableCommunicationDevices();
method @Nullable public android.media.AudioDeviceInfo getCommunicationDevice();
method public android.media.AudioDeviceInfo[] getDevices(int);
method public static int getDirectPlaybackSupport(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
method public int getEncodedSurroundMode();
method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
method public String getParameters(String);
method public static int getPlaybackOffloadSupport(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
method @Deprecated public static int getPlaybackOffloadSupport(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
method public String getProperty(String);
method public int getRingerMode();
method @Deprecated public int getRouting(int);
@@ -20844,6 +20845,10 @@ package android.media {
field public static final int AUDIOFOCUS_REQUEST_FAILED = 0; // 0x0
field public static final int AUDIOFOCUS_REQUEST_GRANTED = 1; // 0x1
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
field public static final int DIRECT_PLAYBACK_BITSTREAM_SUPPORTED = 4; // 0x4
field public static final int DIRECT_PLAYBACK_NOT_SUPPORTED = 0; // 0x0
field public static final int DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = 3; // 0x3
field public static final int DIRECT_PLAYBACK_OFFLOAD_SUPPORTED = 1; // 0x1
field public static final int ENCODED_SURROUND_OUTPUT_ALWAYS = 2; // 0x2
field public static final int ENCODED_SURROUND_OUTPUT_AUTO = 0; // 0x0
field public static final int ENCODED_SURROUND_OUTPUT_MANUAL = 3; // 0x3
@@ -21234,7 +21239,7 @@ package android.media {
method public int getStreamType();
method public boolean getTimestamp(android.media.AudioTimestamp);
method public int getUnderrunCount();
method public static boolean isDirectPlaybackSupported(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
method @Deprecated public static boolean isDirectPlaybackSupported(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
method public boolean isOffloadedPlayback();
method public void pause() throws java.lang.IllegalStateException;
method public void play() throws java.lang.IllegalStateException;

View File

@@ -1479,6 +1479,9 @@ package android.media {
field public static final int DEVICE_ROLE_DISABLED = 2; // 0x2
field public static final int DEVICE_ROLE_NONE = 0; // 0x0
field public static final int DEVICE_ROLE_PREFERRED = 1; // 0x1
field public static final int DIRECT_BITSTREAM_SUPPORTED = 4; // 0x4
field public static final int DIRECT_OFFLOAD_GAPLESS_SUPPORTED = 3; // 0x3
field public static final int DIRECT_OFFLOAD_SUPPORTED = 1; // 0x1
field public static final int OFFLOAD_GAPLESS_SUPPORTED = 2; // 0x2
field public static final int OFFLOAD_SUPPORTED = 1; // 0x1
field public static final int STREAM_DEFAULT = -1; // 0xffffffff

View File

@@ -2774,6 +2774,46 @@ static jboolean android_media_AudioSystem_canBeSpatialized(JNIEnv *env, jobject
return canBeSpatialized;
}
// keep these values in sync with AudioSystem.java
#define DIRECT_NOT_SUPPORTED 0
#define DIRECT_OFFLOAD_SUPPORTED 1
#define DIRECT_OFFLOAD_GAPLESS_SUPPORTED 3
#define DIRECT_BITSTREAM_SUPPORTED 4
static jint convertAudioDirectModeFromNative(audio_direct_mode_t directMode) {
jint result = DIRECT_NOT_SUPPORTED;
if ((directMode | AUDIO_DIRECT_OFFLOAD_SUPPORTED) != AUDIO_DIRECT_NOT_SUPPORTED) {
result |= DIRECT_OFFLOAD_SUPPORTED;
}
if ((directMode | AUDIO_DIRECT_OFFLOAD_GAPLESS_SUPPORTED) != AUDIO_DIRECT_NOT_SUPPORTED) {
result |= DIRECT_OFFLOAD_GAPLESS_SUPPORTED;
}
if ((directMode | AUDIO_DIRECT_BITSTREAM_SUPPORTED) != AUDIO_DIRECT_NOT_SUPPORTED) {
result |= DIRECT_BITSTREAM_SUPPORTED;
}
return result;
}
static jint android_media_AudioSystem_getDirectPlaybackSupport(JNIEnv *env, jobject thiz,
jobject jFormat, jobject jaa) {
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
return AUDIO_DIRECT_NOT_SUPPORTED;
}
audio_config_t nConfig;
javaAudioFormatToNativeAudioConfig(env, &nConfig, jFormat, false /*isInput*/);
audio_direct_mode_t directMode;
status_t status = AudioSystem::getDirectPlaybackSupport(paa.get(), &nConfig, &directMode);
if (status != NO_ERROR) {
ALOGW("%s native returned error %d", __func__, status);
return AUDIO_DIRECT_NOT_SUPPORTED;
}
return convertAudioDirectModeFromNative(directMode);
}
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] =
@@ -2917,7 +2957,10 @@ static const JNINativeMethod gMethods[] =
{"canBeSpatialized",
"(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;"
"[Landroid/media/AudioDeviceAttributes;)Z",
(void *)android_media_AudioSystem_canBeSpatialized}};
(void *)android_media_AudioSystem_canBeSpatialized},
{"getDirectPlaybackSupport",
"(Landroid/media/AudioFormat;Landroid/media/AudioAttributes;)I",
(void *)android_media_AudioSystem_getDirectPlaybackSupport}};
static const JNINativeMethod gEventHandlerMethods[] = {
{"native_setup",

View File

@@ -2397,6 +2397,77 @@ public class AudioManager {
}
}
//====================================================================
// Direct playback query
/** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}:
direct playback not supported. */
public static final int DIRECT_PLAYBACK_NOT_SUPPORTED = AudioSystem.DIRECT_NOT_SUPPORTED;
/** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}:
direct offload playback supported. Compressed offload is a variant of direct playback.
It is the feature that allows audio processing tasks to be done on the Android device but
not on the application processor, instead, it is handled by dedicated hardware such as audio
DSPs. That will allow the application processor to be idle as much as possible, which is
good for power saving. Compressed offload playback supports
{@link AudioTrack.StreamEventCallback} for event notifications. */
public static final int DIRECT_PLAYBACK_OFFLOAD_SUPPORTED =
AudioSystem.DIRECT_OFFLOAD_SUPPORTED;
/** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}:
direct offload playback supported with gapless transitions. Compressed offload is a variant
of direct playback. It is the feature that allows audio processing tasks to be done on the
Android device but not on the application processor, instead, it is handled by dedicated
hardware such as audio DSPs. That will allow the application processor to be idle as much as
possible, which is good for power saving. Compressed offload playback supports
{@link AudioTrack.StreamEventCallback} for event notifications. Gapless transitions
indicates the ability to play consecutive audio tracks without an audio silence in
between. */
public static final int DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED =
AudioSystem.DIRECT_OFFLOAD_GAPLESS_SUPPORTED;
/** Return value for {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)}:
direct playback supported. This value covers direct playback that is bitstream pass-through
such as compressed pass-through. */
public static final int DIRECT_PLAYBACK_BITSTREAM_SUPPORTED =
AudioSystem.DIRECT_BITSTREAM_SUPPORTED;
/** @hide */
@IntDef(flag = true, prefix = "DIRECT_PLAYBACK_", value = {
DIRECT_PLAYBACK_NOT_SUPPORTED,
DIRECT_PLAYBACK_OFFLOAD_SUPPORTED,
DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED,
DIRECT_PLAYBACK_BITSTREAM_SUPPORTED}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDirectPlaybackMode {}
/**
* Returns a bitfield representing the different forms of direct playback currently available
* for a given audio format.
* <p>Direct playback means that the audio stream is not altered by the framework. The audio
* stream will not be resampled, volume scaled, downmixed or mixed with other content by
* the framework. But it may be wrapped in a higher level protocol such as IEC61937 for
* passthrough.
* <p>Checking for direct support can help the app select the representation of audio content
* that most closely matches the capabilities of the device and peripherals (e.g. A/V receiver)
* connected to it. Note that the provided stream can still be re-encoded or mixed with other
* streams, if needed.
* @param format the audio format (codec, sample rate, channels) being checked.
* @param attributes the {@link AudioAttributes} to be used for playback
* @return the direct playback mode available with given format and attributes. The returned
* value will be {@link #DIRECT_PLAYBACK_NOT_SUPPORTED} or a combination of
* {@link #DIRECT_PLAYBACK_OFFLOAD_SUPPORTED},
* {@link #DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} and
* {@link #DIRECT_PLAYBACK_BITSTREAM_SUPPORTED}. Note that if
* {@link #DIRECT_PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} is present in the returned value,
* then {@link #DIRECT_PLAYBACK_OFFLOAD_SUPPORTED} will be too.
*/
@AudioDirectPlaybackMode
public static int getDirectPlaybackSupport(@NonNull AudioFormat format,
@NonNull AudioAttributes attributes) {
Objects.requireNonNull(format);
Objects.requireNonNull(attributes);
return AudioSystem.getDirectPlaybackSupport(format, attributes);
}
//====================================================================
// Offload query
/**
@@ -2457,7 +2528,9 @@ public class AudioManager {
* {@link #PLAYBACK_OFFLOAD_SUPPORTED} if offload playback is supported or
* {@link #PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} if gapless transitions are
* also supported.
* @deprecated Use {@link #getDirectPlaybackSupport(AudioFormat, AudioAttributes)} instead
*/
@Deprecated
@AudioOffloadMode
public static int getPlaybackOffloadSupport(@NonNull AudioFormat format,
@NonNull AudioAttributes attributes) {

View File

@@ -1766,15 +1766,36 @@ public class AudioSystem
*/
public static native int setAllowedCapturePolicy(int uid, int flags);
/**
* @hide
* Direct playback modes supported by audio HAL implementation.
*/
public static final int DIRECT_NOT_SUPPORTED = 0;
public static final int DIRECT_OFFLOAD_SUPPORTED = 1;
public static final int DIRECT_OFFLOAD_GAPLESS_SUPPORTED = 3;
public static final int DIRECT_BITSTREAM_SUPPORTED = 4;
/**
* @hide
* Compressed audio offload decoding modes supported by audio HAL implementation.
* Keep in sync with system/media/include/media/audio.h.
*/
public static final int OFFLOAD_NOT_SUPPORTED = 0;
public static final int OFFLOAD_SUPPORTED = 1;
public static final int OFFLOAD_NOT_SUPPORTED = DIRECT_NOT_SUPPORTED;
public static final int OFFLOAD_SUPPORTED = DIRECT_OFFLOAD_SUPPORTED;
public static final int OFFLOAD_GAPLESS_SUPPORTED = 2;
/**
* @hide
* Returns how direct playback of an audio format is currently available on the device.
* @param format the audio format (codec, sample rate, channels) being checked.
* @param attributes the {@link AudioAttributes} to be used for playback
* @return the direct playback mode available with given format and attributes. Any combination
* of {@link #DIRECT_NOT_SUPPORTED}, {@link #DIRECT_OFFLOAD_SUPPORTED},
* {@link #DIRECT_OFFLOAD_GAPLESS_SUPPORTED} and {@link #DIRECT_BITSTREAM_SUPPORTED}.
*/
public static native int getDirectPlaybackSupport(
@NonNull AudioFormat format, @NonNull AudioAttributes attributes);
static int getOffloadSupport(@NonNull AudioFormat format, @NonNull AudioAttributes attr) {
return native_get_offload_support(format.getEncoding(), format.getSampleRate(),
format.getChannelMask(), format.getChannelIndexMask(),

View File

@@ -1275,8 +1275,8 @@ public class AudioTrack extends PlayerBase
throw new UnsupportedOperationException(
"Offload and low latency modes are incompatible");
}
if (AudioSystem.getOffloadSupport(mFormat, mAttributes)
== AudioSystem.OFFLOAD_NOT_SUPPORTED) {
if (AudioSystem.getDirectPlaybackSupport(mFormat, mAttributes)
== AudioSystem.DIRECT_NOT_SUPPORTED) {
throw new UnsupportedOperationException(
"Cannot create AudioTrack, offload format / attributes not supported");
}
@@ -1438,7 +1438,10 @@ public class AudioTrack extends PlayerBase
* the audio data.
* @param attributes a non-null {@link AudioAttributes} instance.
* @return true if the given audio format can be played directly.
* @deprecated Use {@link AudioManager#getDirectPlaybackSupport(AudioFormat, AudioAttributes)}
* instead.
*/
@Deprecated
public static boolean isDirectPlaybackSupported(@NonNull AudioFormat format,
@NonNull AudioAttributes attributes) {
if (format == null) {