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

Commit 3e1acc0c authored by Eric Laurent's avatar Eric Laurent
Browse files

refactor AudioRecord and AudioFlinger openRecord()

Refactor the mechanism used by audio record tracks to query and
attach to an input mixer/stream in audio flinger. This will:
 - reduce the number of binder transactions needed to create a record track
 - move sample rate, framecount and flags validations to audio server side
 - move audio session allocation to audio server side
 - prepare restriction of certain binder transactions to audioserver only

Also:
 - renamed openRecord() to createRecord() for consistency with AudioTrack
 - make AudioRecord mStatus update consistent when calling default
 contructor + set() or constructor with arguments
 - make AudioClient, CreateTrackXXX and  CreateRecordXXX classes derive
 from Parcelable
 - restore audio session ID validity check in AudioFlinger::createTrack()

Test: CTS tests: AudioRecordTest, AudioRecordingConfigurationTest, AudioPreProcessingTest
Test: manual test for capture use cases: camcorder, OK Google, VoIP calls
Change-Id: I72edaa7ddef1da11c77df21e88378e3aa9012d58
parent eda72c27
Loading
Loading
Loading
Loading
+104 −174
Original line number Original line Diff line number Diff line
@@ -69,8 +69,7 @@ AudioRecord::AudioRecord(const String16 &opPackageName)
    : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName),
    : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName),
      mSessionId(AUDIO_SESSION_ALLOCATE),
      mSessionId(AUDIO_SESSION_ALLOCATE),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE)
      mPortId(AUDIO_PORT_HANDLE_NONE)
{
{
}
}


@@ -97,10 +96,9 @@ AudioRecord::AudioRecord(
      mSessionId(AUDIO_SESSION_ALLOCATE),
      mSessionId(AUDIO_SESSION_ALLOCATE),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousSchedulingGroup(SP_DEFAULT),
      mPreviousSchedulingGroup(SP_DEFAULT),
      mProxy(NULL),
      mProxy(NULL)
      mPortId(AUDIO_PORT_HANDLE_NONE)
{
{
    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
    (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
            uid, pid, pAttributes, selectedDeviceId);
            uid, pid, pAttributes, selectedDeviceId);
}
}
@@ -151,6 +149,11 @@ status_t AudioRecord::set(
        const audio_attributes_t* pAttributes,
        const audio_attributes_t* pAttributes,
        audio_port_handle_t selectedDeviceId)
        audio_port_handle_t selectedDeviceId)
{
{
    status_t status = NO_ERROR;
    uint32_t channelCount;
    pid_t callingPid;
    pid_t myPid;

    ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
    ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
          "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
          "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
          "uid %d, pid %d",
          "uid %d, pid %d",
@@ -170,7 +173,8 @@ status_t AudioRecord::set(
    case TRANSFER_CALLBACK:
    case TRANSFER_CALLBACK:
        if (cbf == NULL) {
        if (cbf == NULL) {
            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
            return BAD_VALUE;
            status = BAD_VALUE;
            goto exit;
        }
        }
        break;
        break;
    case TRANSFER_OBTAIN:
    case TRANSFER_OBTAIN:
@@ -178,14 +182,16 @@ status_t AudioRecord::set(
        break;
        break;
    default:
    default:
        ALOGE("Invalid transfer type %d", transferType);
        ALOGE("Invalid transfer type %d", transferType);
        return BAD_VALUE;
        status = BAD_VALUE;
        goto exit;
    }
    }
    mTransfer = transferType;
    mTransfer = transferType;


    // invariant that mAudioRecord != 0 is true only after set() returns successfully
    // invariant that mAudioRecord != 0 is true only after set() returns successfully
    if (mAudioRecord != 0) {
    if (mAudioRecord != 0) {
        ALOGE("Track already in use");
        ALOGE("Track already in use");
        return INVALID_OPERATION;
        status = INVALID_OPERATION;
        goto exit;
    }
    }


    if (pAttributes == NULL) {
    if (pAttributes == NULL) {
@@ -209,16 +215,18 @@ status_t AudioRecord::set(
    // AudioFlinger capture only supports linear PCM
    // AudioFlinger capture only supports linear PCM
    if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
    if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
        ALOGE("Format %#x is not linear pcm", format);
        ALOGE("Format %#x is not linear pcm", format);
        return BAD_VALUE;
        status = BAD_VALUE;
        goto exit;
    }
    }
    mFormat = format;
    mFormat = format;


    if (!audio_is_input_channel(channelMask)) {
    if (!audio_is_input_channel(channelMask)) {
        ALOGE("Invalid channel mask %#x", channelMask);
        ALOGE("Invalid channel mask %#x", channelMask);
        return BAD_VALUE;
        status = BAD_VALUE;
        goto exit;
    }
    }
    mChannelMask = channelMask;
    mChannelMask = channelMask;
    uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
    channelCount = audio_channel_count_from_in_mask(channelMask);
    mChannelCount = channelCount;
    mChannelCount = channelCount;


    if (audio_is_linear_pcm(format)) {
    if (audio_is_linear_pcm(format)) {
@@ -227,28 +235,24 @@ status_t AudioRecord::set(
        mFrameSize = sizeof(uint8_t);
        mFrameSize = sizeof(uint8_t);
    }
    }


    // mFrameCount is initialized in openRecord_l
    // mFrameCount is initialized in createRecord_l
    mReqFrameCount = frameCount;
    mReqFrameCount = frameCount;


    mNotificationFramesReq = notificationFrames;
    mNotificationFramesReq = notificationFrames;
    // mNotificationFramesAct is initialized in openRecord_l
    // mNotificationFramesAct is initialized in createRecord_l


    if (sessionId == AUDIO_SESSION_ALLOCATE) {
        mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
    } else {
    mSessionId = sessionId;
    mSessionId = sessionId;
    }
    ALOGV("set(): mSessionId %d", mSessionId);
    ALOGV("set(): mSessionId %d", mSessionId);


    int callingpid = IPCThreadState::self()->getCallingPid();
    callingPid = IPCThreadState::self()->getCallingPid();
    int mypid = getpid();
    myPid = getpid();
    if (uid == AUDIO_UID_INVALID || (callingpid != mypid)) {
    if (uid == AUDIO_UID_INVALID || (callingPid != myPid)) {
        mClientUid = IPCThreadState::self()->getCallingUid();
        mClientUid = IPCThreadState::self()->getCallingUid();
    } else {
    } else {
        mClientUid = uid;
        mClientUid = uid;
    }
    }
    if (pid == -1 || (callingpid != mypid)) {
    if (pid == -1 || (callingPid != myPid)) {
        mClientPid = callingpid;
        mClientPid = callingPid;
    } else {
    } else {
        mClientPid = pid;
        mClientPid = pid;
    }
    }
@@ -263,7 +267,7 @@ status_t AudioRecord::set(
    }
    }


    // create the IAudioRecord
    // create the IAudioRecord
    status_t status = openRecord_l(0 /*epoch*/, mOpPackageName);
    status = createRecord_l(0 /*epoch*/, mOpPackageName);


    if (status != NO_ERROR) {
    if (status != NO_ERROR) {
        if (mAudioRecordThread != 0) {
        if (mAudioRecordThread != 0) {
@@ -271,10 +275,9 @@ status_t AudioRecord::set(
            mAudioRecordThread->requestExitAndWait();
            mAudioRecordThread->requestExitAndWait();
            mAudioRecordThread.clear();
            mAudioRecordThread.clear();
        }
        }
        return status;
        goto exit;
    }
    }


    mStatus = NO_ERROR;
    mUserData = user;
    mUserData = user;
    // TODO: add audio hardware input latency here
    // TODO: add audio hardware input latency here
    mLatency = (1000LL * mFrameCount) / mSampleRate;
    mLatency = (1000LL * mFrameCount) / mSampleRate;
@@ -289,7 +292,9 @@ status_t AudioRecord::set(
    mFramesRead = 0;
    mFramesRead = 0;
    mFramesReadServerOffset = 0;
    mFramesReadServerOffset = 0;


    return NO_ERROR;
exit:
    mStatus = status;
    return status;
}
}


// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
@@ -540,70 +545,29 @@ const char * AudioRecord::convertTransferToText(transfer_type transferType) {
}
}


// must be called with mLock held
// must be called with mLock held
status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
{
{
    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    IAudioFlinger::CreateRecordInput input;
    IAudioFlinger::CreateRecordOutput output;
    audio_session_t originalSessionId;
    sp<media::IAudioRecord> record;
    void *iMemPointer;
    audio_track_cblk_t* cblk;
    status_t status;

    if (audioFlinger == 0) {
    if (audioFlinger == 0) {
        ALOGE("Could not get audioflinger");
        ALOGE("Could not get audioflinger");
        return NO_INIT;
        status = NO_INIT;
        goto exit;
    }
    }


    audio_io_handle_t input;

    // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
    // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
    // After fast request is denied, we will request again if IAudioRecord is re-created.
    // After fast request is denied, we will request again if IAudioRecord is re-created.


    status_t status;

    // Not a conventional loop, but a retry loop for at most two iterations total.
    // Try first maybe with FAST flag then try again without FAST flag if that fails.
    // Exits loop normally via a return at the bottom, or with error via a break.
    // The sp<> references will be dropped when re-entering scope.
    // The lack of indentation is deliberate, to reduce code churn and ease merges.
    for (;;) {
    audio_config_base_t config  = {
            .sample_rate = mSampleRate,
            .channel_mask = mChannelMask,
            .format = mFormat
        };
    mRoutedDeviceId = mSelectedDeviceId;
    status = AudioSystem::getInputForAttr(&mAttributes, &input,
                                        mSessionId,
                                        // FIXME compare to AudioTrack
                                        mClientPid,
                                        mClientUid,
                                        &config,
                                        mFlags, &mRoutedDeviceId, &mPortId);

    if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE) {
        ALOGE("Could not get audio input for session %d, record source %d, sample rate %u, "
              "format %#x, channel mask %#x, flags %#x",
              mSessionId, mAttributes.source, mSampleRate, mFormat, mChannelMask, mFlags);
        return BAD_VALUE;
    }

    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
    // we must release it ourselves if anything goes wrong.
    // we must release it ourselves if anything goes wrong.


#if 0
    size_t afFrameCount;
    status = AudioSystem::getFrameCount(input, &afFrameCount);
    if (status != NO_ERROR) {
        ALOGE("getFrameCount(input=%d) status %d", input, status);
        break;
    }
#endif

    uint32_t afSampleRate;
    status = AudioSystem::getSamplingRate(input, &afSampleRate);
    if (status != NO_ERROR) {
        ALOGE("getSamplingRate(input=%d) status %d", input, status);
        break;
    }
    if (mSampleRate == 0) {
        mSampleRate = afSampleRate;
    }

    // Client can only express a preference for FAST.  Server will perform additional tests.
    // Client can only express a preference for FAST.  Server will perform additional tests.
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
        bool useCaseAllowed =
        bool useCaseAllowed =
@@ -622,66 +586,41 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
        if (!useCaseAllowed) {
        if (!useCaseAllowed) {
            ALOGW("AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
            ALOGW("AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
                  convertTransferToText(mTransfer));
                  convertTransferToText(mTransfer));
        }

        // sample rates must also match
        bool sampleRateAllowed = mSampleRate == afSampleRate;
        if (!sampleRateAllowed) {
            ALOGW("AUDIO_INPUT_FLAG_FAST denied, rates do not match %u Hz, require %u Hz",
                  mSampleRate, afSampleRate);
        }

        bool fastAllowed = useCaseAllowed && sampleRateAllowed;
        if (!fastAllowed) {
            mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
            mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
                    AUDIO_INPUT_FLAG_RAW));
                    AUDIO_INPUT_FLAG_RAW));
            AudioSystem::releaseInput(input, mSessionId);
            continue;   // retry
        }
        }
    }
    }


    // The notification frame count is the period between callbacks, as suggested by the client
    input.attr = mAttributes;
    // but moderated by the server.  For record, the calculations are done entirely on server side.
    input.config.sample_rate = mSampleRate;
    size_t notificationFrames = mNotificationFramesReq;
    input.config.channel_mask = mChannelMask;
    size_t frameCount = mReqFrameCount;
    input.config.format = mFormat;

    input.clientInfo.clientUid = mClientUid;
    audio_input_flags_t flags = mFlags;
    input.clientInfo.clientPid = mClientPid;

    input.clientInfo.clientTid = -1;
    pid_t tid = -1;
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
        if (mAudioRecordThread != 0) {
        if (mAudioRecordThread != 0) {
            tid = mAudioRecordThread->getTid();
            input.clientInfo.clientTid = mAudioRecordThread->getTid();
        }
        }
    }
    }
    input.opPackageName = opPackageName;


    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
    input.flags = mFlags;
                                // but we will still need the original value also
    // The notification frame count is the period between callbacks, as suggested by the client
    audio_session_t originalSessionId = mSessionId;
    // but moderated by the server.  For record, the calculations are done entirely on server side.
    input.frameCount = mReqFrameCount;
    input.notificationFrameCount = mNotificationFramesReq;
    input.selectedDeviceId = mSelectedDeviceId;
    input.sessionId = mSessionId;
    originalSessionId = mSessionId;


    sp<IMemory> iMem;           // for cblk
    record = audioFlinger->createRecord(input,
    sp<IMemory> bufferMem;
                                                              output,
    sp<media::IAudioRecord> record = audioFlinger->openRecord(input,
                                                              &status);
                                                              mSampleRate,
                                                              mFormat,
                                                              mChannelMask,
                                                              opPackageName,
                                                              &temp,
                                                              &flags,
                                                              mClientPid,
                                                              tid,
                                                              mClientUid,
                                                              &mSessionId,
                                                              &notificationFrames,
                                                              iMem,
                                                              bufferMem,
                                                              &status,
                                                              mPortId);
    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
            "session ID changed from %d to %d", originalSessionId, mSessionId);


    if (status != NO_ERROR) {
    if (status != NO_ERROR) {
        ALOGE("AudioFlinger could not create record track, status: %d", status);
        ALOGE("AudioFlinger could not create record track, status: %d", status);
        break;
        goto exit;
    }
    }
    ALOG_ASSERT(record != 0);
    ALOG_ASSERT(record != 0);


@@ -689,41 +628,41 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
    // so we are no longer responsible for releasing it.
    // so we are no longer responsible for releasing it.


    mAwaitBoost = false;
    mAwaitBoost = false;
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
    if (output.flags & AUDIO_INPUT_FLAG_FAST) {
        if (flags & AUDIO_INPUT_FLAG_FAST) {
        ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu",
            ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", frameCount, temp);
              mReqFrameCount, output.frameCount);
        mAwaitBoost = true;
        mAwaitBoost = true;
        } else {
            ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu -> %zu", frameCount, temp);
            mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
                    AUDIO_INPUT_FLAG_RAW));
            continue;   // retry
        }
    }
    }
    mFlags = flags;
    mFlags = output.flags;
    mRoutedDeviceId = output.selectedDeviceId;
    mSessionId = output.sessionId;
    mSampleRate = output.sampleRate;


    if (iMem == 0) {
    if (output.cblk == 0) {
        ALOGE("Could not get control block");
        ALOGE("Could not get control block");
        return NO_INIT;
        status = NO_INIT;
        goto exit;
    }
    }
    void *iMemPointer = iMem->pointer();
    iMemPointer = output.cblk ->pointer();
    if (iMemPointer == NULL) {
    if (iMemPointer == NULL) {
        ALOGE("Could not get control block pointer");
        ALOGE("Could not get control block pointer");
        return NO_INIT;
        status = NO_INIT;
        goto exit;
    }
    }
    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
    cblk = static_cast<audio_track_cblk_t*>(iMemPointer);


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


@@ -733,43 +672,42 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
        mDeathNotifier.clear();
        mDeathNotifier.clear();
    }
    }
    mAudioRecord = record;
    mAudioRecord = record;
    mCblkMemory = iMem;
    mCblkMemory = output.cblk;
    mBufferMemory = bufferMem;
    mBufferMemory = output.buffers;
    IPCThreadState::self()->flushCommands();
    IPCThreadState::self()->flushCommands();


    mCblk = cblk;
    mCblk = cblk;
    // note that temp is the (possibly revised) value of frameCount
    // note that output.frameCount is the (possibly revised) value of mReqFrameCount
    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
    if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
        ALOGW("Requested frameCount %zu but received frameCount %zu",
              mReqFrameCount,  output.frameCount);
    }
    }
    frameCount = temp;


    // Make sure that application is notified with sufficient margin before overrun.
    // Make sure that application is notified with sufficient margin before overrun.
    // The computation is done on server side.
    // The computation is done on server side.
    if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) {
    if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
        ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu",
        ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu",
                mNotificationFramesReq, notificationFrames, frameCount);
                mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
    }
    }
    mNotificationFramesAct = (uint32_t) notificationFrames;
    mNotificationFramesAct = (uint32_t)output.notificationFrameCount;



    //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
    //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
    if (mDeviceCallback != 0 && mInput != input) {
    if (mDeviceCallback != 0 && mInput != output.inputId) {
        if (mInput != AUDIO_IO_HANDLE_NONE) {
        if (mInput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(this, mInput);
            AudioSystem::removeAudioDeviceCallback(this, mInput);
        }
        }
        AudioSystem::addAudioDeviceCallback(this, input);
        AudioSystem::addAudioDeviceCallback(this, output.inputId);
    }
    }


    // We retain a copy of the I/O handle, but don't own the reference
    // We retain a copy of the I/O handle, but don't own the reference
    mInput = input;
    mInput = output.inputId;
    mRefreshRemaining = true;
    mRefreshRemaining = true;


    mFrameCount = frameCount;
    mFrameCount = output.frameCount;
    // If IAudioRecord is re-created, don't let the requested frameCount
    // If IAudioRecord is re-created, don't let the requested frameCount
    // decrease.  This can confuse clients that cache frameCount().
    // decrease.  This can confuse clients that cache frameCount().
    if (frameCount > mReqFrameCount) {
    if (mFrameCount > mReqFrameCount) {
        mReqFrameCount = frameCount;
        mReqFrameCount = mFrameCount;
    }
    }


    // update proxy
    // update proxy
@@ -780,17 +718,9 @@ status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16
    mDeathNotifier = new DeathNotifier(this);
    mDeathNotifier = new DeathNotifier(this);
    IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
    IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);


    return NO_ERROR;
exit:

    mStatus = status;
    // End of retry loop.
    // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
    // The lack of indentation is deliberate, to reduce code churn and ease merges.
    }

// Arrive here on error, via a break
    AudioSystem::releaseInput(input, mSessionId);
    if (status == NO_ERROR) {
        status = NO_INIT;
    }
    return status;
    return status;
}
}


@@ -1222,12 +1152,12 @@ status_t AudioRecord::restoreRecord_l(const char *from)


    mFlags = mOrigFlags;
    mFlags = mOrigFlags;


    // if the new IAudioRecord is created, openRecord_l() will modify the
    // if the new IAudioRecord is created, createRecord_l() will modify the
    // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
    // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
    // It will also delete the strong references on previous IAudioRecord and IMemory
    // It will also delete the strong references on previous IAudioRecord and IMemory
    Modulo<uint32_t> position(mProxy->getPosition());
    Modulo<uint32_t> position(mProxy->getPosition());
    mNewPosition = position + mUpdatePeriod;
    mNewPosition = position + mUpdatePeriod;
    status_t result = openRecord_l(position, mOpPackageName);
    status_t result = createRecord_l(position, mOpPackageName);
    if (result == NO_ERROR) {
    if (result == NO_ERROR) {
        if (mActive) {
        if (mActive) {
            // callback thread or sync event hasn't changed
            // callback thread or sync event hasn't changed
+46 −117

File changed.

Preview size limit exceeded, changes collapsed.

+1 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.media;
package android.media;


/* Native code must specify namespace media (media::IAudioRecord) when referring to this class */
interface IAudioRecord {
interface IAudioRecord {


  /* After it's created the track is not active. Call start() to
  /* After it's created the track is not active. Call start() to
+4 −3
Original line number Original line Diff line number Diff line
@@ -19,12 +19,13 @@
#define ANDROID_AUDIO_CLIENT_H
#define ANDROID_AUDIO_CLIENT_H


#include <binder/Parcel.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <system/audio.h>
#include <system/audio.h>
#include <utils/String16.h>
#include <utils/String16.h>


namespace android {
namespace android {


class AudioClient {
class AudioClient : public Parcelable {
 public:
 public:
    AudioClient() :
    AudioClient() :
        clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {}
        clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {}
@@ -34,7 +35,7 @@ class AudioClient {
    pid_t clientTid;
    pid_t clientTid;
    String16 packageName;
    String16 packageName;


    status_t readFromParcel(Parcel *parcel) {
    status_t readFromParcel(const Parcel *parcel) override {
        clientUid = parcel->readInt32();
        clientUid = parcel->readInt32();
        clientPid = parcel->readInt32();
        clientPid = parcel->readInt32();
        clientTid = parcel->readInt32();
        clientTid = parcel->readInt32();
@@ -42,7 +43,7 @@ class AudioClient {
        return NO_ERROR;
        return NO_ERROR;
    }
    }


    status_t writeToParcel(Parcel *parcel) const {
    status_t writeToParcel(Parcel *parcel) const override {
        parcel->writeInt32(clientUid);
        parcel->writeInt32(clientUid);
        parcel->writeInt32(clientPid);
        parcel->writeInt32(clientPid);
        parcel->writeInt32(clientTid);
        parcel->writeInt32(clientTid);
+1 −2
Original line number Original line Diff line number Diff line
@@ -570,7 +570,7 @@ private:


            // caller must hold lock on mLock for all _l methods
            // caller must hold lock on mLock for all _l methods


            status_t openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName);
            status_t createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName);


            // FIXME enum is faster than strcmp() for parameter 'from'
            // FIXME enum is faster than strcmp() for parameter 'from'
            status_t restoreRecord_l(const char *from);
            status_t restoreRecord_l(const char *from);
@@ -682,7 +682,6 @@ private:
                                              // May not match the app selection depending on other
                                              // May not match the app selection depending on other
                                              // activity and connected devices
                                              // activity and connected devices
    wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
    wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
    audio_port_handle_t    mPortId;  // unique ID allocated by audio policy


};
};


Loading