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

Commit aa31cfab authored by Alexy Joseph's avatar Alexy Joseph Committed by Steve Kondik
Browse files

libmedia: Enable TrackOffload for more usecases

Enable offloading of apps that set attributes.
Handle device switch cleanly and retry
offloading.

CRs-Fixed: 860260
Change-Id: I97f21014cf6fb44fe00ad869e0b052992a6a7e18
parent e47a66b9
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -690,6 +690,7 @@ protected:
            static bool decideTrackOffloadFromStreamType(const audio_stream_type_t sType);

            static bool decideTrackOffloadfromAttributes(const audio_attributes_t *pAttributes);
            void initializeTrackOffloadParams();
    // Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
#ifdef QCOM_DIRECTTRACK
    sp<IDirectTrack>        mDirectTrack;
@@ -714,8 +715,10 @@ protected:

    // constant after constructor or set()
    audio_format_t          mFormat;                // as requested by client, not forced to 16-bit
    audio_format_t          mOriginalFormat;
    audio_stream_type_t     mStreamType;            // mStreamType == AUDIO_STREAM_DEFAULT implies
                                                    // this AudioTrack has valid attributes
    bool                    mValidStreamType;
    uint32_t                mChannelCount;
    audio_channel_mask_t    mChannelMask;
    sp<IMemory>             mSharedBuffer;
@@ -723,11 +726,14 @@ protected:
    audio_offload_info_t    mOffloadInfoCopy;
    const audio_offload_info_t* mOffloadInfo;
    audio_attributes_t      mAttributes;
    bool                    mValidAttributes;

    // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data.  For 8-bit PCM data, it's
    // twice as large as mFrameSize because data is expanded to 16-bit before it's stored in buffer.
    size_t                  mFrameSize;             // app-level frame size
    size_t                  mOriginalFrameSize;
    size_t                  mFrameSizeAF;           // AudioFlinger frame size
    size_t                  mOriginalFrameSizeAF;

    status_t                mStatus;

@@ -790,6 +796,8 @@ protected:
    void*                   mObserver;
#endif

    audio_output_flags_t    mOriginalFlags;
    bool                    mSavedParams;
        // const after set(), except for bits AUDIO_OUTPUT_FLAG_FAST and AUDIO_OUTPUT_FLAG_OFFLOAD.
        // mLock must be held to read or write those bits reliably.

+71 −17
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ AudioTrack::AudioTrack()
    mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
    mAttributes.usage = AUDIO_USAGE_UNKNOWN;
    mAttributes.flags = 0x0;
    initializeTrackOffloadParams();
    strcpy(mAttributes.tags, "");
}

@@ -151,7 +152,6 @@ AudioTrack::AudioTrack(
      mIsTimed(false),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousSchedulingGroup(SP_DEFAULT),
      mUseSmallBuf(false),
#ifdef QCOM_DIRECTTRACK
      mPausedPosition(0),
      mAudioFlinger(NULL),
@@ -167,6 +167,7 @@ AudioTrack::AudioTrack(
    mAttributes.flags = 0x0;
    strcpy(mAttributes.tags, "");
#endif
    initializeTrackOffloadParams();
    mStatus = set(streamType, sampleRate, format, channelMask,
            frameCount, flags, cbf, user, notificationFrames,
            0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
@@ -193,7 +194,6 @@ AudioTrack::AudioTrack(
      mIsTimed(false),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousSchedulingGroup(SP_DEFAULT),
      mUseSmallBuf(false),
#ifdef QCOM_DIRECTTRACK
      mPausedPosition(0),
      mAudioFlinger(NULL),
@@ -208,6 +208,7 @@ AudioTrack::AudioTrack(
    mAttributes.flags = 0x0;
    strcpy(mAttributes.tags, "");
#endif
    initializeTrackOffloadParams();
    mStatus = set(streamType, sampleRate, format, channelMask,
            0 /*frameCount*/, flags, cbf, user, notificationFrames,
            sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
@@ -265,7 +266,6 @@ bool AudioTrack::canOffloadTrack(
             return false;
        }


       // Track offload only if the following criterion
       // 1. Track offload info structure should NOT have been provided
       // 2. Format is 16 bit
@@ -273,11 +273,13 @@ bool AudioTrack::canOffloadTrack(
       // 4. Client uses write interface to provide data


       // Track offload does not base any decision on mAttributes, or channelMask for now
       // Track offload does not base any decision channelMask for now
       // The value in attributes gets preference over stream type

        if (!offloadInfo &&
             (format == AUDIO_FORMAT_PCM_16_BIT) &&
             (streamType == AUDIO_STREAM_MUSIC) &&
             ((streamType == AUDIO_STREAM_MUSIC) ||
             decideTrackOffloadfromAttributes(attributes)) &&
             (flags == AUDIO_OUTPUT_FLAG_NONE) &&
             (transferType != TRANSFER_CALLBACK))
        {
@@ -286,6 +288,10 @@ bool AudioTrack::canOffloadTrack(
            mPcmTrackOffloadInfo.format = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD;
            mPcmTrackOffloadInfo.sample_rate  = mSampleRate;
            mPcmTrackOffloadInfo.channel_mask = channelMask;
            if (mValidAttributes) {
                ALOGV("Setting stream type from attributes");
                streamType = audio_attributes_to_stream_type(attributes);
            }
            mPcmTrackOffloadInfo.stream_type = streamType;
            mPcmTrackOffloadInfo.duration_us = 0xFFFFFFFF;
            //TODO: Use mAttributes and pass the value of content in this field
@@ -308,6 +314,14 @@ bool AudioTrack::canOffloadTrack(
              " channel mask %#x, flags %#x, transferType %d, offloadInfo %p",
              streamType, attributes->usage, mSampleRate, format, channelMask, flags,
              transferType, offloadInfo);
        if (mSavedParams) {
            mFlags = mOriginalFlags;
            mFrameSize = mOriginalFrameSize;
            mFrameSizeAF = mOriginalFrameSizeAF;
            mFormat = mOriginalFormat;
            mUseSmallBuf = false;
            mIsPcmTrackOffloaded = false;
        }
        return false;
}
status_t AudioTrack::set(
@@ -382,12 +396,12 @@ status_t AudioTrack::set(
        ALOGE("Track already in use");
        return INVALID_OPERATION;
    }

    mCanOffloadPcmTrack = decideTrackOffloadFromStreamType(streamType);

    // handle default values first.
    if (streamType == AUDIO_STREAM_DEFAULT) {
        mValidStreamType = false;
        streamType = AUDIO_STREAM_MUSIC;
    } else {
        mValidStreamType = true;
    }

    if (pAttributes == NULL) {
@@ -396,13 +410,13 @@ status_t AudioTrack::set(
            return BAD_VALUE;
        }
        mStreamType = streamType;

        mValidAttributes = false;
    } else {
        // stream type shouldn't be looked at, this track has audio attributes
        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
        ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]",
                mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
        mCanOffloadPcmTrack = decideTrackOffloadfromAttributes(&mAttributes);
        mValidAttributes = true;
        mStreamType = AUDIO_STREAM_DEFAULT;
    }

@@ -1229,13 +1243,23 @@ status_t AudioTrack::createTrack_l()
    audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
    mIsPcmTrackOffloaded = false;
    mPcmTrackOffloadInfo = AUDIO_INFO_INITIALIZER;
    if (mValidAttributes) {
        mCanOffloadPcmTrack = decideTrackOffloadfromAttributes(&mAttributes);
    } else if (mValidStreamType) {
        mCanOffloadPcmTrack = decideTrackOffloadFromStreamType(mStreamType);
    }

    // Check if the track can be offloaded. Store the decision in mCanOffloadPcmTrack
    // if stream type was not set, then do not try to offload track
    if (mCanOffloadPcmTrack) {
        if (mSavedParams) {
            mCanOffloadPcmTrack = canOffloadTrack(mStreamType, mOriginalFormat, mChannelMask, mOriginalFlags,
                                      mTransfer, &mAttributes, mOffloadInfo);
        } else {
            mCanOffloadPcmTrack = canOffloadTrack(mStreamType, mFormat, mChannelMask, mFlags,
                                      mTransfer, &mAttributes, mOffloadInfo);
        }
    }

    if(mCanOffloadPcmTrack) {
        ALOGV("TrackOffload: Tying to create PCM Offload track");
@@ -1250,10 +1274,25 @@ status_t AudioTrack::createTrack_l()
            //got output
            ALOGV("TrackOffload: Going through PCM Offload Track");
            mIsPcmTrackOffloaded = true;
            mSavedParams = true;
            mOriginalFrameSize = mFrameSize;
            mOriginalFrameSizeAF = mFrameSizeAF;
            mOriginalFormat = mFormat;
            mOriginalFlags = mFlags;
            mFlags = flags;
            mFrameSize = sizeof(uint8_t);
            mFrameSizeAF = sizeof(uint8_t);
            mUseSmallBuf = true;
        } else {
            ALOGV("getOutput failed in track offload, resetting params");
            if (mSavedParams) {
                mFlags = mOriginalFlags;
                mFrameSize = mOriginalFrameSize;
                mFrameSizeAF = mOriginalFrameSizeAF;
                mFormat = mOriginalFormat;
                mUseSmallBuf = false;
                mIsPcmTrackOffloaded = false;
             }
        }
    }

@@ -1263,7 +1302,7 @@ status_t AudioTrack::createTrack_l()
                                                        (audio_session_t)mSessionId, &streamType,
                                                        mSampleRate, mFormat, mChannelMask,
                                                        mFlags, mOffloadInfo);

        ALOGV("retrieving regular output");
    }

    if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
@@ -2229,7 +2268,7 @@ status_t AudioTrack::restoreTrack_l(const char *from)
    // output parameters and new IAudioFlinger in createTrack_l()
    AudioSystem::clearAudioConfigCache();

    if (isOffloadedOrDirect_l()) {
    if (isOffloadedOrDirect_l() && !mIsPcmTrackOffloaded) {
        // FIXME re-creation of offloaded tracks is not yet implemented
        return DEAD_OBJECT;
    }
@@ -2612,7 +2651,8 @@ void AudioTrack::AudioTrackThread::pauseInternal(nsecs_t ns)
    mPausedNs = ns;
}

bool AudioTrack::decideTrackOffloadFromStreamType(const audio_stream_type_t sType){
bool AudioTrack::decideTrackOffloadFromStreamType(const audio_stream_type_t sType)
{

   bool decision = false;
   if(sType != AUDIO_STREAM_DEFAULT) {
@@ -2622,7 +2662,8 @@ bool AudioTrack::decideTrackOffloadFromStreamType(const audio_stream_type_t sTyp
   return decision;
}

bool AudioTrack::decideTrackOffloadfromAttributes(const audio_attributes_t *pAttributes) {
bool AudioTrack::decideTrackOffloadfromAttributes(const audio_attributes_t *pAttributes)
{

    bool decision = false;
    if (pAttributes == NULL) {
@@ -2640,4 +2681,17 @@ bool AudioTrack::decideTrackOffloadfromAttributes(const audio_attributes_t *pAtt
    return decision;
}

void AudioTrack::initializeTrackOffloadParams()
{
    mUseSmallBuf  = false;
    mSavedParams = false;
    mValidAttributes = false;
    mValidStreamType = false;
    mOriginalFrameSize = 0;
    mOriginalFrameSizeAF = 0;
    mOriginalFormat = AUDIO_FORMAT_DEFAULT;
    mOriginalFlags = AUDIO_OUTPUT_FLAG_NONE;
    mIsPcmTrackOffloaded = false;
    mCanOffloadPcmTrack = false;
}
}; // namespace android