Merge "AudioManager: add reporting of gapless playback support"

This commit is contained in:
Eric Laurent
2020-12-11 07:09:29 +00:00
committed by Android (Google) Code Review
6 changed files with 75 additions and 12 deletions

View File

@@ -24470,6 +24470,7 @@ package android.media {
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 public String getProperty(String);
method public int getRingerMode();
method @Deprecated public int getRouting(int);
@@ -24588,6 +24589,9 @@ package android.media {
field public static final int MODE_NORMAL = 0; // 0x0
field public static final int MODE_RINGTONE = 1; // 0x1
field @Deprecated public static final int NUM_STREAMS = 5; // 0x5
field public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = 2; // 0x2
field public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = 0; // 0x0
field public static final int PLAYBACK_OFFLOAD_SUPPORTED = 1; // 0x1
field public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = "android.media.property.OUTPUT_FRAMES_PER_BUFFER";
field public static final String PROPERTY_OUTPUT_SAMPLE_RATE = "android.media.property.OUTPUT_SAMPLE_RATE";
field public static final String PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED = "android.media.property.SUPPORT_AUDIO_SOURCE_UNPROCESSED";

View File

@@ -1009,6 +1009,8 @@ 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 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

@@ -2083,10 +2083,9 @@ android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz,
(audio_devices_t)device);
}
static jboolean
android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask, jint streamType)
{
static jint android_media_AudioSystem_getOffloadSupport(JNIEnv *env, jobject thiz, jint encoding,
jint sampleRate, jint channelMask,
jint channelIndexMask, jint streamType) {
audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
format.format = (audio_format_t) audioFormatToNative(encoding);
format.sample_rate = (uint32_t) sampleRate;
@@ -2098,7 +2097,7 @@ android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
// client side code cannot access "audio.offload.min.duration.secs" property to make a query
// agnostic of duration, so using acceptable estimate of 2mn
format.duration_us = 120 * 1000000;
return AudioSystem::isOffloadSupported(format);
return AudioSystem::getOffloadSupport(format);
}
static jint
@@ -2574,8 +2573,8 @@ static const JNINativeMethod gMethods[] =
(void *)android_media_AudioSystem_registerRecordingCallback},
{"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
{"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
{"native_is_offload_supported", "(IIIII)Z",
(void *)android_media_AudioSystem_isOffloadSupported},
{"native_get_offload_support", "(IIIII)I",
(void *)android_media_AudioSystem_getOffloadSupport},
{"getMicrophones", "(Ljava/util/ArrayList;)I",
(void *)android_media_AudioSystem_getMicrophones},
{"getSurroundFormats", "(Ljava/util/Map;Z)I",

View File

@@ -2319,7 +2319,55 @@ public class AudioManager {
if (attributes == null) {
throw new NullPointerException("Illegal null AudioAttributes");
}
return AudioSystem.isOffloadSupported(format, attributes);
return AudioSystem.getOffloadSupport(format, attributes) != PLAYBACK_OFFLOAD_NOT_SUPPORTED;
}
/** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}:
offload playback not supported */
public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = AudioSystem.OFFLOAD_NOT_SUPPORTED;
/** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}:
offload playback supported */
public static final int PLAYBACK_OFFLOAD_SUPPORTED = AudioSystem.OFFLOAD_SUPPORTED;
/** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}:
offload playback supported with gapless transitions */
public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED =
AudioSystem.OFFLOAD_GAPLESS_SUPPORTED;
/** @hide */
@IntDef(flag = false, prefix = "PLAYBACK_OFFLOAD_", value = {
PLAYBACK_OFFLOAD_NOT_SUPPORTED,
PLAYBACK_OFFLOAD_SUPPORTED,
PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED }
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioOffloadMode {}
/**
* Returns whether offloaded playback of an audio format is supported on the device or not and
* when supported whether gapless transitions are possible or not.
* <p>Offloaded playback is the feature where the decoding and playback of an audio stream
* is not competing with other software resources. In general, it is supported by dedicated
* hardware, such as audio DSPs.
* <p>Note that this query only provides information about the support of an audio format,
* it does not indicate whether the resources necessary for the offloaded playback are
* available at that instant.
* @param format the audio format (codec, sample rate, channels) being checked.
* @param attributes the {@link AudioAttributes} to be used for playback
* @return {@link #PLAYBACK_OFFLOAD_NOT_SUPPORTED} if offload playback if not supported,
* {@link #PLAYBACK_OFFLOAD_SUPPORTED} if offload playback is supported or
* {@link #PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} if gapless transitions are
* also supported.
*/
@AudioOffloadMode
public static int getPlaybackOffloadSupport(@NonNull AudioFormat format,
@NonNull AudioAttributes attributes) {
if (format == null) {
throw new NullPointerException("Illegal null AudioFormat");
}
if (attributes == null) {
throw new NullPointerException("Illegal null AudioAttributes");
}
return AudioSystem.getOffloadSupport(format, attributes);
}
//====================================================================

View File

@@ -1639,13 +1639,22 @@ public class AudioSystem
*/
public static native int setAllowedCapturePolicy(int uid, int flags);
static boolean isOffloadSupported(@NonNull AudioFormat format, @NonNull AudioAttributes attr) {
return native_is_offload_supported(format.getEncoding(), format.getSampleRate(),
/**
* @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_GAPLESS_SUPPORTED = 2;
static int getOffloadSupport(@NonNull AudioFormat format, @NonNull AudioAttributes attr) {
return native_get_offload_support(format.getEncoding(), format.getSampleRate(),
format.getChannelMask(), format.getChannelIndexMask(),
attr.getVolumeControlStream());
}
private static native boolean native_is_offload_supported(int encoding, int sampleRate,
private static native int native_get_offload_support(int encoding, int sampleRate,
int channelMask, int channelIndexMask, int streamType);
/** @hide */

View File

@@ -1256,7 +1256,8 @@ public class AudioTrack extends PlayerBase
throw new UnsupportedOperationException(
"Offload and low latency modes are incompatible");
}
if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) {
if (AudioSystem.getOffloadSupport(mFormat, mAttributes)
== AudioSystem.OFFLOAD_NOT_SUPPORTED) {
throw new UnsupportedOperationException(
"Cannot create AudioTrack, offload format / attributes not supported");
}