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

Commit d776ac63 authored by Glenn Kasten's avatar Glenn Kasten
Browse files

IAudioFlinger::openRecord returns IMemory(s)

openRecord() now explicitly returns the control block and data buffer
as separate IMemory references.  If the IMemory for data buffer
is 0, this means it immediately follows the control block.

Change-Id: Ic098f88f0e037f8fbe30006689e18cacacf09d06
parent 0c5b910e
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -490,10 +490,12 @@ private:
    int                     mSessionId;
    transfer_type           mTransfer;

    // Next 4 fields may be changed if IAudioRecord is re-created, but always != 0
    // Next 5 fields may be changed if IAudioRecord is re-created, but always != 0
    // provided the initial set() was successful
    sp<IAudioRecord>        mAudioRecord;
    sp<IMemory>             mCblkMemory;
    audio_track_cblk_t*     mCblk;              // re-load after mLock.unlock()
    sp<IMemory>             mBufferMemory;
    audio_io_handle_t       mInput;             // returned by AudioSystem::getInput()

    int                     mPreviousPriority;  // before start()
+2 −0
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ public:
                                track_flags_t *flags,
                                pid_t tid,  // -1 means unused, otherwise must be valid non-0
                                int *sessionId,
                                sp<IMemory>& cblk,
                                sp<IMemory>& buffers,   // return value 0 means it follows cblk
                                status_t *status) = 0;

    /* query the audio hardware state. This state never changes,
+24 −8
Original line number Diff line number Diff line
@@ -484,6 +484,8 @@ status_t AudioRecord::openRecord_l(size_t epoch)
    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
                                // but we will still need the original value also
    int originalSessionId = mSessionId;
    sp<IMemory> iMem;           // for cblk
    sp<IMemory> bufferMem;
    sp<IAudioRecord> record = audioFlinger->openRecord(input,
                                                       mSampleRate, mFormat,
                                                       mChannelMask,
@@ -491,6 +493,8 @@ status_t AudioRecord::openRecord_l(size_t epoch)
                                                       &trackFlags,
                                                       tid,
                                                       &mSessionId,
                                                       iMem,
                                                       bufferMem,
                                                       &status);
    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
            "session ID changed from %d to %d", originalSessionId, mSessionId);
@@ -504,7 +508,6 @@ status_t AudioRecord::openRecord_l(size_t epoch)
    // AudioFlinger now owns the reference to the I/O handle,
    // so we are no longer responsible for releasing it.

    sp<IMemory> iMem = record->getCblk();
    if (iMem == 0) {
        ALOGE("Could not get control block");
        return NO_INIT;
@@ -514,6 +517,22 @@ status_t AudioRecord::openRecord_l(size_t epoch)
        ALOGE("Could not get control block pointer");
        return NO_INIT;
    }
    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);

    // Starting address of buffers in shared memory.
    // The buffers are either immediately after the control block,
    // or in a separate area at discretion of server.
    void *buffers;
    if (bufferMem == 0) {
        buffers = cblk + 1;
    } else {
        buffers = bufferMem->pointer();
        if (buffers == NULL) {
            ALOGE("Could not get buffer pointer");
            return NO_INIT;
        }
    }

    // invariant that mAudioRecord != 0 is true only after set() returns successfully
    if (mAudioRecord != 0) {
        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
@@ -522,7 +541,7 @@ status_t AudioRecord::openRecord_l(size_t epoch)
    mAudioRecord = record;

    mCblkMemory = iMem;
    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
    mBufferMemory = bufferMem;
    mCblk = cblk;
    // note that temp is the (possibly revised) value of frameCount
    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
@@ -552,11 +571,6 @@ status_t AudioRecord::openRecord_l(size_t epoch)
    mInput = input;
    mRefreshRemaining = true;

    // Starting address of buffers in shared memory, immediately after the control block.  This
    // address is for the mapping within client address space.  AudioFlinger::TrackBase::mBuffer
    // is for the server address space.
    void *buffers = (char*)cblk + sizeof(audio_track_cblk_t);

    mFrameCount = frameCount;
    // If IAudioRecord is re-created, don't let the requested frameCount
    // decrease.  This can confuse clients that cache frameCount().
@@ -631,6 +645,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r
        // keep them from going away if another thread re-creates the track during obtainBuffer()
        sp<AudioRecordClientProxy> proxy;
        sp<IMemory> iMem;
        sp<IMemory> bufferMem;
        {
            // start of lock scope
            AutoMutex lock(mLock);
@@ -654,6 +669,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *r
            // Keep the extra references
            proxy = mProxy;
            iMem = mCblkMemory;
            bufferMem = mBufferMemory;

            // Non-blocking if track is stopped
            if (!mActive) {
@@ -986,7 +1002,7 @@ status_t AudioRecord::restoreRecord_l(const char *from)
    status_t result;

    // if the new IAudioRecord is created, openRecord_l() will modify the
    // following member variables: mAudioRecord, mCblkMemory and mCblk.
    // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
    // It will also delete the strong references on previous IAudioRecord and IMemory
    size_t position = mProxy->getPosition();
    mNewPosition = position + mUpdatePeriod;
+30 −4
Original line number Diff line number Diff line
@@ -169,6 +169,8 @@ public:
                                track_flags_t *flags,
                                pid_t tid,
                                int *sessionId,
                                sp<IMemory>& cblk,
                                sp<IMemory>& buffers,
                                status_t *status)
    {
        Parcel data, reply;
@@ -188,6 +190,8 @@ public:
            lSessionId = *sessionId;
        }
        data.writeInt32(lSessionId);
        cblk.clear();
        buffers.clear();
        status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply);
        if (lStatus != NO_ERROR) {
            ALOGE("openRecord error: %s", strerror(-lStatus));
@@ -206,17 +210,34 @@ public:
            }
            lStatus = reply.readInt32();
            record = interface_cast<IAudioRecord>(reply.readStrongBinder());
            cblk = interface_cast<IMemory>(reply.readStrongBinder());
            if (cblk != 0 && cblk->pointer() == NULL) {
                cblk.clear();
            }
            buffers = interface_cast<IMemory>(reply.readStrongBinder());
            if (buffers != 0 && buffers->pointer() == NULL) {
                buffers.clear();
            }
            if (lStatus == NO_ERROR) {
                if (record == 0) {
                    ALOGE("openRecord should have returned an IAudioRecord");
                    lStatus = UNKNOWN_ERROR;
                } else if (cblk == 0) {
                    ALOGE("openRecord should have returned a cblk");
                    lStatus = NO_MEMORY;
                }
                // buffers is permitted to be 0
            } else {
                if (record != 0) {
                    ALOGE("openRecord returned an IAudioRecord but with status %d", lStatus);
                    record.clear();
                if (record != 0 || cblk != 0 || buffers != 0) {
                    ALOGE("openRecord returned an IAudioRecord, cblk, "
                          "or buffers but with status %d", lStatus);
                }
            }
            if (lStatus != NO_ERROR) {
                record.clear();
                cblk.clear();
                buffers.clear();
            }
        }
        if (status != NULL) {
            *status = lStatus;
@@ -838,15 +859,20 @@ status_t BnAudioFlinger::onTransact(
            track_flags_t flags = (track_flags_t) data.readInt32();
            pid_t tid = (pid_t) data.readInt32();
            int sessionId = data.readInt32();
            sp<IMemory> cblk;
            sp<IMemory> buffers;
            status_t status;
            sp<IAudioRecord> record = openRecord(input,
                    sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, &status);
                    sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId,
                    cblk, buffers, &status);
            LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR));
            reply->writeInt64(frameCount);
            reply->writeInt32(flags);
            reply->writeInt32(sessionId);
            reply->writeInt32(status);
            reply->writeStrongBinder(record->asBinder());
            reply->writeStrongBinder(cblk->asBinder());
            reply->writeStrongBinder(buffers->asBinder());
            return NO_ERROR;
        } break;
        case SAMPLE_RATE: {
+8 −0
Original line number Diff line number Diff line
@@ -1313,6 +1313,8 @@ sp<IAudioRecord> AudioFlinger::openRecord(
        IAudioFlinger::track_flags_t *flags,
        pid_t tid,
        int *sessionId,
        sp<IMemory>& cblk,
        sp<IMemory>& buffers,
        status_t *status)
{
    sp<RecordThread::RecordTrack> recordTrack;
@@ -1321,6 +1323,9 @@ sp<IAudioRecord> AudioFlinger::openRecord(
    status_t lStatus;
    int lSessionId;

    cblk.clear();
    buffers.clear();

    // check calling permissions
    if (!recordingAllowed()) {
        ALOGE("openRecord() permission denied: recording not allowed");
@@ -1396,6 +1401,9 @@ sp<IAudioRecord> AudioFlinger::openRecord(
        goto Exit;
    }

    cblk = recordTrack->getCblk();
    buffers = recordTrack->getBuffers();

    // return handle to client
    recordHandle = new RecordHandle(recordTrack);

Loading