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

Commit 0996f2b4 authored by jiabin's avatar jiabin
Browse files

Add offload support for aaudio.

Bug: 372041799
Test: atest AAudioTests
Flag: EXEMPT NDK
Change-Id: I34ffa52f600b3de234eb327307321db2562853c9
parent 91ece572
Loading
Loading
Loading
Loading
+158 −3
Original line number Diff line number Diff line
@@ -119,8 +119,42 @@ enum {
     *
     * Available since API level 34.
     */
    AAUDIO_FORMAT_IEC61937
    AAUDIO_FORMAT_IEC61937,

    /**
     * This format is used for audio compressed in MP3 format.
     */
    AAUDIO_FORMAT_MP3,

    /**
     * This format is used for audio compressed in AAC LC format.
     */
    AAUDIO_FORMAT_AAC_LC,

    /**
     * This format is used for audio compressed in AAC HE V1 format.
     */
    AAUDIO_FORMAT_AAC_HE_V1,

    /**
     * This format is used for audio compressed in AAC HE V2 format.
     */
    AAUDIO_FORMAT_AAC_HE_V2,

    /**
     * This format is used for audio compressed in AAC ELD format.
     */
    AAUDIO_FORMAT_AAC_ELD,

    /**
     * This format is used for audio compressed in AAC XHE format.
     */
    AAUDIO_FORMAT_AAC_XHE,

    /**
     * This format is used for audio compressed in OPUS.
     */
    AAUDIO_FORMAT_OPUS
};
typedef int32_t aaudio_format_t;

@@ -335,7 +369,23 @@ enum {
    /**
     * Reducing latency is more important than battery life.
     */
    AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
    AAUDIO_PERFORMANCE_MODE_LOW_LATENCY,

    /**
     * Extending battery life is more important than low latency.
     *
     * This mode is not supported in input streams.
     * This mode will play through the offloaded audio path to save battery life.
     *
     * Comparing to mode {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING}, the stream at
     * this mode will be able to write a large amount(several seconds) of data within a
     * short time. The written data will be queued in a hardware buffer. After that, the
     * app can suspend its thread/process that playing audio, the audio framework's data
     * pipe will be suspended automatically and the CPU will be allowed to sleep for
     * power saving. When all queued data are played, the apps will be able to get callback
     * to feed more data.
     */
    AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED
};
typedef int32_t aaudio_performance_mode_t;

@@ -1090,7 +1140,8 @@ AAUDIO_API void AAudioStreamBuilder_setBufferCapacityInFrames(
 * Set the requested performance mode.
 *
 * Supported modes are {@link #AAUDIO_PERFORMANCE_MODE_NONE},
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING} * and {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY}.
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING}, {@link #AAUDIO_PERFORMANCE_MODE_LOW_LATENCY} and
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED}.
 *
 * The default, if you do not call this function, is {@link #AAUDIO_PERFORMANCE_MODE_NONE}.
 *
@@ -1474,6 +1525,44 @@ AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* _Nonnu
        AAudioStream_errorCallback _Nullable callback, void* _Nullable userData)
        __INTRODUCED_IN(26);

/**
 * Prototype for the callback function that is passed to
 * AAudioStreamBuilder_setPresentationEndCallback().
 *
 * This will be called when all the buffers of an offloaded stream that were queued in the audio
 * system (e.g. the combination of the Android audio framework and the device's audio hardware)
 * have been played after AudioStream_requestStop() has been called.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream(), which must be an
 *               output stream as the offloaded mode is only supported for output stream
 * @param userData the same address that was passed to
 *                 AAudioStreamBuilder_setPresentationEndCallback().
 */
typedef void (*AAudioStream_presentationEndCallback)(AAudioStream* _Nonnull stream,
                                                     void* _Null_unspecified userData);

/**
 * Request that AAudio call this function when all the buffers of an offloaded stream that were
 * queued in the audio system (e.g. the combination of the Android audio framework and the device's
 * audio hardware) have been played.
 *
 * The presentation end callback must be used together with the data callback.
 * The presentation edn callback won't be called if the stream is closed before all the data
 * is played.
 *
 * Available since API level 36.
 *
 * @param builder reference provided by AAudio_createStreamBuilder()
 * @param callback pointer to a function that will be called when all the buffers of an offloaded
 *                 stream that were queued have been played.
 * @param userData pointer to an application data structure that will be passed
 *                 to the callback functions.
 */
AAUDIO_API void AAudioStreamBuilder_setPresentationEndCallback(
        AAudioStreamBuilder* _Nonnull builder,
        AAudioStream_presentationEndCallback _Nonnull callback,
        void* _Nullable userData) __INTRODUCED_IN(36);

/**
 * Open a stream based on the options in the StreamBuilder.
 *
@@ -2188,6 +2277,72 @@ AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* _Nonnull stream)
AAUDIO_API aaudio_channel_mask_t AAudioStream_getChannelMask(AAudioStream* _Nonnull stream)
        __INTRODUCED_IN(32);

/**
 * Configures the delay and padding values for the current stream playing in offload mode.
 * This should only be used on a stream whose performance mode is
 * {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED} and the format is compressed format.
 * The unit is frames, where a frame includes samples for all audio channels, e.g. 100 frames
 * for a stereo stream corresponds to 200 interleaved PCM samples.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @param delayInFrames number of frames to be ignored at the beginning of the stream. A value
 *                      of 0 indicates no delay is to be applied.
 * @param paddingInFrames number of frames to be ignored at the end of the stream. A value of 0
 *                        of 0 indicates no padding is to be applied.
 * @return {@link #AAUDIO_OK} if the delay and padding values are set successfully,
 *         or {@link #AAUDIO_ERROR_ILLEGAL_ARGUMENT} if delayInFrames or paddingInFrames
 *         is less than 0,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API aaudio_result_t AAudioStream_setOffloadDelayPadding(
        AAudioStream* _Nonnull stream, int32_t delayInFrames, int32_t paddingInFrames)
        __INTRODUCED_IN(36);

/**
 * Return the decoder delay of an offloaded stream in frames.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return the offload delay in frames that previously set with
 *         {@link #AAudioStream_setOffloadDelayPadding},
 *         or 0 if it was never modified,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API int32_t AAudioStream_getOffloadDelay(AAudioStream* _Nonnull stream) __INTRODUCED_IN(36);

/**
 * Return the decoder padding of an offloaded stream in frames.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return the offload padding in frames that previously set with
 *         {@link #AAudioStream_setOffloadDelayPadding},
 *         or 0 if it was never modified,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API int32_t AAudioStream_getOffloadPadding(AAudioStream* _Nonnull stream)
        __INTRODUCED_IN(36);

/**
 * Declares that the last data writing operation on this stream provided the last buffer of this
 * stream.
 * After the end of stream, previously set padding and delay values are ignored. That indicates
 * all written data will be played.
 * Use this method in the same thread as any data writing operation.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return {@link #AAUDIO_OK} on success,
 *         or {@link #AAUDIO_ERROR_UNIMPLEMENTED} if the stream is not an output stream whose
 *         performance mode is {@link #AAUDIO_PERFORMANCE_MODE_POWER_SAVING_OFFLOADED},
 *         or {@link #AAUDIO_ERROR_INVALID_STATE} if the stream is not yet initialized.
 */
AAUDIO_API aaudio_result_t AAudioStream_setOffloadEndOfStream(AAudioStream* _Nonnull stream)
        __INTRODUCED_IN(36);

#ifdef __cplusplus
}
#endif
+34 −0
Original line number Diff line number Diff line
@@ -255,6 +255,16 @@ AAUDIO_API void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builde
    streamBuilder->setErrorCallbackUserData(userData);
}

AAUDIO_API void AAudioStreamBuilder_setPresentationEndCallback(AAudioStreamBuilder* builder,
        AAudioStream_presentationEndCallback callback, void* userData) {
    AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
    if (streamBuilder == nullptr) {
        return;
    }
    streamBuilder->setPresentationEndCallbackProc(callback)
                 ->setPresentationEndCallbackUserData(userData);
}

AAUDIO_API void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder,
                                                int32_t frames)
{
@@ -693,3 +703,27 @@ AAUDIO_API aaudio_channel_mask_t AAudioStream_getChannelMask(AAudioStream* strea
    // Do not return channel index masks as they are not public.
    return AAudio_isChannelIndexMask(channelMask) ? AAUDIO_UNSPECIFIED : channelMask;
}

AAUDIO_API aaudio_result_t AAudioStream_setOffloadDelayPadding(
        AAudioStream* stream, int32_t delayInFrames, int32_t paddingInFrames) {
    if (delayInFrames < 0 || paddingInFrames < 0) {
        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    }
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->setOffloadDelayPadding(delayInFrames, paddingInFrames);
}

AAUDIO_API int32_t AAudioStream_getOffloadDelay(AAudioStream* stream) {
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->getOffloadDelay();
}

AAUDIO_API int32_t AAudioStream_getOffloadPadding(AAudioStream* stream) {
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->getOffloadPadding();
}

AAUDIO_API aaudio_result_t AAudioStream_setOffloadEndOfStream(AAudioStream* stream) {
    AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
    return audioStream->setOffloadEndOfStream();
}
+7 −0
Original line number Diff line number Diff line
@@ -58,6 +58,13 @@ static aaudio_result_t isFormatValid(audio_format_t format) {
        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
        case AUDIO_FORMAT_PCM_8_24_BIT:
        case AUDIO_FORMAT_IEC61937:
        case AUDIO_FORMAT_MP3:
        case AUDIO_FORMAT_AAC_LC:
        case AUDIO_FORMAT_AAC_HE_V1:
        case AUDIO_FORMAT_AAC_HE_V2:
        case AUDIO_FORMAT_AAC_ELD:
        case AUDIO_FORMAT_AAC_XHE:
        case AUDIO_FORMAT_OPUS:
            break; // valid
        default:
            ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
+6 −0
Original line number Diff line number Diff line
@@ -116,6 +116,8 @@ aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
    mErrorCallbackProc = builder.getErrorCallbackProc();
    mDataCallbackUserData = builder.getDataCallbackUserData();
    mErrorCallbackUserData = builder.getErrorCallbackUserData();
    setPresentationEndCallbackUserData(builder.getPresentationEndCallbackUserData());
    setPresentationEndCallbackProc(builder.getPresentationEndCallbackProc());

    return AAUDIO_OK;
}
@@ -285,6 +287,10 @@ aaudio_result_t AudioStream::safeFlush() {

aaudio_result_t AudioStream::systemStopInternal() {
    std::lock_guard<std::mutex> lock(mStreamLock);
    return systemStopInternal_l();
}

aaudio_result_t AudioStream::systemStopInternal_l() {
    aaudio_result_t result = safeStop_l();
    if (result == AAUDIO_OK) {
        // We only call this for logging in "dumpsys audio". So ignore return code.
+25 −5
Original line number Diff line number Diff line
@@ -332,7 +332,7 @@ public:
     * have been called.
     */
    int32_t getBytesPerFrame() const {
        return mSamplesPerFrame * getBytesPerSample();
        return audio_bytes_per_frame(mSamplesPerFrame, mFormat);
    }

    /**
@@ -346,7 +346,7 @@ public:
     * This is only valid after setDeviceSamplesPerFrame() and setDeviceFormat() have been called.
     */
    int32_t getBytesPerDeviceFrame() const {
        return getDeviceSamplesPerFrame() * audio_bytes_per_sample(getDeviceFormat());
        return audio_bytes_per_frame(getDeviceSamplesPerFrame(), getDeviceFormat());
    }

    virtual int64_t getFramesWritten() = 0;
@@ -390,6 +390,24 @@ public:
        mDeviceSamplesPerFrame = deviceSamplesPerFrame;
    }

    virtual aaudio_result_t setOffloadDelayPadding(int32_t delayInFrames, int32_t paddingInFrames) {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual int32_t getOffloadDelay() {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual int32_t getOffloadPadding() {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual aaudio_result_t setOffloadEndOfStream() EXCLUDES(mStreamLock) {
        return AAUDIO_ERROR_UNIMPLEMENTED;
    }

    virtual void setPresentationEndCallbackProc(AAudioStream_presentationEndCallback proc) { }
    virtual void setPresentationEndCallbackUserData(void* userData) { }

    /**
     * @return true if data callback has been specified
@@ -408,7 +426,7 @@ public:
    /**
     * @return true if called from the same thread as the callback
     */
    bool collidesWithCallback() const;
    virtual bool collidesWithCallback() const;

    // Implement AudioDeviceCallback
    void onAudioDeviceUpdate(audio_io_handle_t audioIo,
@@ -649,6 +667,8 @@ protected:

    aaudio_result_t joinThread_l(void **returnArg) REQUIRES(mStreamLock);

    virtual aaudio_result_t systemStopInternal_l() REQUIRES(mStreamLock);

    std::atomic<bool>    mCallbackEnabled{false};

    float                mDuckAndMuteVolume = 1.0f;
@@ -742,6 +762,8 @@ protected:
        mAudioBalance = audioBalance;
    }

    aaudio_result_t safeStop_l() REQUIRES(mStreamLock);

    std::string mMetricsId; // set once during open()

    std::mutex                 mStreamLock;
@@ -750,8 +772,6 @@ protected:

private:

    aaudio_result_t safeStop_l() REQUIRES(mStreamLock);

    /**
     * Release then close the stream.
     */
Loading