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

Commit 08f09685 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "Offload support for android.media.AudioTrack"

parents bd70ed4c 03f51393
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -22662,6 +22662,7 @@ package android.media {
    method public boolean isBluetoothScoOn();
    method public boolean isMicrophoneMute();
    method public boolean isMusicActive();
    method public static boolean isOffloadedPlaybackSupported(android.media.AudioFormat);
    method public boolean isSpeakerphoneOn();
    method public boolean isStreamMute(int);
    method public boolean isVolumeFixed();
@@ -22983,6 +22984,7 @@ package android.media {
    method public int getUnderrunCount();
    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);
    method public void release();
    method public int reloadStaticData();
    method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
@@ -23003,6 +23005,7 @@ package android.media {
    method public deprecated int setStereoVolume(float, float);
    method public int setVolume(float);
    method public void stop() throws java.lang.IllegalStateException;
    method public void unregisterStreamEventCallback(android.media.AudioTrack.StreamEventCallback);
    method public int write(byte[], int, int);
    method public int write(byte[], int, int, int);
    method public int write(short[], int, int);
@@ -23036,6 +23039,7 @@ package android.media {
    method public android.media.AudioTrack.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
    method public android.media.AudioTrack.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
    method public android.media.AudioTrack.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
    method public android.media.AudioTrack.Builder setOffloadedPlayback(boolean);
    method public android.media.AudioTrack.Builder setPerformanceMode(int);
    method public android.media.AudioTrack.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
    method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
@@ -23059,6 +23063,13 @@ package android.media {
    method public default void onRoutingChanged(android.media.AudioRouting);
  }
  public static abstract class AudioTrack.StreamEventCallback {
    ctor public AudioTrack.StreamEventCallback();
    method public void onDataRequest(android.media.AudioTrack, int);
    method public void onPresentationEnded(android.media.AudioTrack);
    method public void onTearDown(android.media.AudioTrack);
  }
  public class CamcorderProfile {
    method public static android.media.CamcorderProfile get(int);
    method public static android.media.CamcorderProfile get(int, int);
+3 −4
Original line number Diff line number Diff line
@@ -128,9 +128,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
        return ENCODING_DOLBY_TRUEHD;
    case AUDIO_FORMAT_AAC_ELD:
        return ENCODING_AAC_ELD;
    // FIXME needs addition of AUDIO_FORMAT_AAC_XHE
    //case AUDIO_FORMAT_AAC_XHE:
    //    return ENCODING_AAC_XHE;
    case AUDIO_FORMAT_AAC_XHE:
        return ENCODING_AAC_XHE;
    case AUDIO_FORMAT_AC4:
        return ENCODING_AC4;
    case AUDIO_FORMAT_E_AC3_JOC:
+40 −27
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>

#include <android-base/macros.h>
#include <binder/MemoryHeapBase.h>
#include <binder/MemoryBase.h>

@@ -134,41 +135,53 @@ static void audioCallback(int event, void* user, void *info) {
        callbackInfo->busy = true;
    }

    // used as default argument when event callback doesn't have any, or number of
    // frames for EVENT_CAN_WRITE_MORE_DATA
    int arg = 0;
    bool postEvent = false;
    switch (event) {
    // Offload only events
    case AudioTrack::EVENT_STREAM_END:
    case AudioTrack::EVENT_MORE_DATA:
    // a.k.a. tear down
    case AudioTrack::EVENT_NEW_IAUDIOTRACK:
    case AudioTrack::EVENT_CAN_WRITE_MORE_DATA:
        // this event will read the info return parameter of the callback:
        // for JNI offload, use the returned size to indicate:
        // 1/ no data is returned through callback, as it's all done through write()
        // 2/ do not wait as AudioTrack does when it receives 0 bytes
        if (callbackInfo->isOffload) {
            JNIEnv *env = AndroidRuntime::getJNIEnv();
            if (user != NULL && env != NULL) {
                env->CallStaticVoidMethod(
                        callbackInfo->audioTrack_class,
                        javaAudioTrackFields.postNativeEventInJava,
                        callbackInfo->audioTrack_ref, event, 0,0, NULL);
                if (env->ExceptionCheck()) {
                    env->ExceptionDescribe();
                    env->ExceptionClear();
            AudioTrack::Buffer* pBuffer = (AudioTrack::Buffer*) info;
            const size_t availableForWrite = pBuffer->size;
            arg = availableForWrite > INT32_MAX ? INT32_MAX : (int) availableForWrite;
            pBuffer->size = 0;
        }
        FALLTHROUGH_INTENDED;
    case AudioTrack::EVENT_STREAM_END:
    case AudioTrack::EVENT_NEW_IAUDIOTRACK: // a.k.a. tear down
        if (callbackInfo->isOffload) {
            postEvent = true;
        }
        } break;
        break;

    // PCM and offload events
    case AudioTrack::EVENT_MARKER:
    case AudioTrack::EVENT_NEW_POS: {
    case AudioTrack::EVENT_NEW_POS:
        postEvent = true;
        break;
    default:
        // event will not be posted
        break;
    }

    if (postEvent) {
        JNIEnv *env = AndroidRuntime::getJNIEnv();
        if (user != NULL && env != NULL) {
        if (env != NULL) {
            env->CallStaticVoidMethod(
                    callbackInfo->audioTrack_class,
                    javaAudioTrackFields.postNativeEventInJava,
                    callbackInfo->audioTrack_ref, event, 0,0, NULL);
                    callbackInfo->audioTrack_ref, event, arg, 0, NULL);
            if (env->ExceptionCheck()) {
                env->ExceptionDescribe();
                env->ExceptionClear();
            }
        }
        } break;
    }

    {
@@ -215,10 +228,10 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
        jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession,
        jlong nativeAudioTrack, jboolean offload) {

    ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d"
        "nativeAudioTrack=0x%" PRIX64,
    ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
        " nativeAudioTrack=0x%" PRIX64 ", offload=%d",
        jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
        nativeAudioTrack);
        nativeAudioTrack, offload);

    sp<AudioTrack> lpTrack = 0;

@@ -318,7 +331,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
        lpJniStorage->mCallbackData.busy = false;

        audio_offload_info_t offloadInfo;
        if (offload) {
        if (offload == JNI_TRUE) {
            offloadInfo = AUDIO_INFO_INITIALIZER;
            offloadInfo.format = format;
            offloadInfo.sample_rate = sampleRateInHertz;
@@ -331,23 +344,23 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
        status_t status = NO_ERROR;
        switch (memoryMode) {
        case MODE_STREAM:

            status = lpTrack->set(
                    AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
                    sampleRateInHertz,
                    format,// word length, PCM
                    nativeChannelMask,
                    frameCount,
                    AUDIO_OUTPUT_FLAG_NONE,
                    offload ? 0 : frameCount,
                    offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_NONE,
                    audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
                    0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
                    0,// shared mem
                    true,// thread can call Java
                    sessionId,// audio session ID
                    AudioTrack::TRANSFER_SYNC,
                    offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
                    offload ? &offloadInfo : NULL,
                    -1, -1,                       // default uid, pid values
                    paa);

            break;

        case MODE_STATIC:
+1 −0
Original line number Diff line number Diff line
@@ -1068,6 +1068,7 @@ public final class AudioFormat implements Parcelable {
        ENCODING_E_AC3_JOC,
        ENCODING_DTS,
        ENCODING_DTS_HD,
        ENCODING_MP3,
        ENCODING_IEC61937,
        ENCODING_AAC_HE_V1,
        ENCODING_AAC_HE_V2,
+10 −4
Original line number Diff line number Diff line
@@ -1379,14 +1379,20 @@ public class AudioManager {
    //====================================================================
    // Offload query
    /**
     * @hide
     * Returns whether offloaded playback of an audio format is supported on the device.
     * Offloaded playback is where the decoding of an audio stream is not competing with other
     * software resources. In general, it is supported by dedicated hardware, such as audio DSPs.
     * <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.
     * @return true if the given audio format can be offloaded.
     */
    public boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) {
    public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) {
        if (format == null) {
            throw new IllegalArgumentException("Illegal null AudioFormat");
        }
        return AudioSystem.isOffloadSupported(format);
    }

Loading