Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e22f6aa6 authored by jiabin's avatar jiabin
Browse files

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
parent 7d148d1b
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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
+44 −1
Original line number Diff line number Diff line
@@ -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",
+73 −0
Original line number Diff line number Diff line
@@ -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) {
+23 −2
Original line number Diff line number Diff line
@@ -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(),
Loading