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

Commit 2de156d1 authored by Michael Chan's avatar Michael Chan Committed by Mikhail Naganov
Browse files

Add AudioTrack.isDirectPlaybackSupported method

The method checks whether the provided AudioFormat can be played
via currently connected output devices w/o SRC or downmixing
by the framework.

Bug: 120044865
Test: atest CtsMediaTestCases:AudioTrackTest#testIsDirectPlaybackSupported
Change-Id: I63e8334a60d48c17999f500d87360f9c71185dfb
parent efd355c1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23349,6 +23349,7 @@ package android.media {
    method public int getStreamType();
    method public boolean getTimestamp(android.media.AudioTimestamp);
    method public int getUnderrunCount();
    method public static boolean isDirectPlaybackSupported(android.media.AudioFormat, android.media.AudioAttributes);
    method public void pause() throws java.lang.IllegalStateException;
    method public void play() throws java.lang.IllegalStateException;
    method public void registerStreamEventCallback(java.util.concurrent.Executor, android.media.AudioTrack.StreamEventCallback);
+21 −0
Original line number Diff line number Diff line
@@ -480,6 +480,24 @@ native_init_failure:
    return (jint) AUDIOTRACK_ERROR_SETUP_NATIVEINITFAILED;
}

// ----------------------------------------------------------------------------
static jboolean
android_media_AudioTrack_is_direct_output_supported(JNIEnv *env, jobject thiz,
                                             jint encoding, jint sampleRate,
                                             jint channelMask, jint channelIndexMask,
                                             jint contentType, jint usage, jint flags) {
    audio_config_base_t config = {};
    audio_attributes_t attributes = {};
    config.format = static_cast<audio_format_t>(audioFormatToNative(encoding));
    config.sample_rate = static_cast<uint32_t>(sampleRate);
    config.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask);
    attributes.content_type = static_cast<audio_content_type_t>(contentType);
    attributes.usage = static_cast<audio_usage_t>(usage);
    attributes.flags = static_cast<audio_flags_mask_t>(flags);
    // ignore source and tags attributes as they don't affect querying whether output is supported
    return AudioTrack::isDirectOutputSupported(config, attributes);
}

// ----------------------------------------------------------------------------
static void
android_media_AudioTrack_start(JNIEnv *env, jobject thiz)
@@ -1298,6 +1316,9 @@ static jint android_media_AudioTrack_get_port_id(JNIEnv *env, jobject thiz) {
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
    // name,              signature,     funcPtr
    {"native_is_direct_output_supported",
                             "(IIIIIII)Z",
                                         (void *)android_media_AudioTrack_is_direct_output_supported},
    {"native_start",         "()V",      (void *)android_media_AudioTrack_start},
    {"native_stop",          "()V",      (void *)android_media_AudioTrack_stop},
    {"native_pause",         "()V",      (void *)android_media_AudioTrack_pause},
+32 −0
Original line number Diff line number Diff line
@@ -995,6 +995,35 @@ public class AudioTrack extends PlayerBase
        }
    }

    /**
     * Returns whether direct playback of an audio format with the provided attributes is
     * currently supported on the system.
     * <p>Direct playback means that the audio stream is not resampled or downmixed
     * by the framework. Checking for direct support can help the app select the representation
     * of audio content that most closely matches the capabilities of the device and peripherials
     * (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.
     * <p>Also note that this query only provides information about the support of an audio format.
     * It does not indicate whether the resources necessary for the playback are available
     * at that instant.
     * @param format a non-null {@link AudioFormat} instance describing the format of
     *   the audio data.
     * @param attributes a non-null {@link AudioAttributes} instance.
     * @return true if the given audio format can be played directly.
     */
    public static boolean isDirectPlaybackSupported(@NonNull AudioFormat format,
            @NonNull AudioAttributes attributes) {
        if (format == null) {
            throw new IllegalArgumentException("Illegal null AudioFormat argument");
        }
        if (attributes == null) {
            throw new IllegalArgumentException("Illegal null AudioAttributes argument");
        }
        return native_is_direct_output_supported(format.getEncoding(), format.getSampleRate(),
                format.getChannelMask(), format.getChannelIndexMask(),
                attributes.getContentType(), attributes.getUsage(), attributes.getFlags());
    }

    // mask of all the positional channels supported, however the allowed combinations
    // are further restricted by the matching left/right rule and
    // AudioSystem.OUT_CHANNEL_COUNT_MAX
@@ -3328,6 +3357,9 @@ public class AudioTrack extends PlayerBase
    // Native methods called from the Java side
    //--------------------

    private static native boolean native_is_direct_output_supported(int encoding, int sampleRate,
            int channelMask, int channelIndexMask, int contentType, int usage, int flags);

    // post-condition: mStreamType is overwritten with a value
    //     that reflects the audio attributes (e.g. an AudioAttributes object with a usage of
    //     AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC