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

Commit cef7b7a6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Revert "refactor AudioRecord and AudioFlinger openRecord()""

parents 316c3176 0aa3c6eb
Loading
Loading
Loading
Loading
+174 −104
Original line number Diff line number Diff line
@@ -69,7 +69,8 @@ AudioRecord::AudioRecord(const String16 &opPackageName)
    : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName),
      mSessionId(AUDIO_SESSION_ALLOCATE),
      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)
{
}

@@ -96,9 +97,10 @@ AudioRecord::AudioRecord(
      mSessionId(AUDIO_SESSION_ALLOCATE),
      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
      mPreviousSchedulingGroup(SP_DEFAULT),
      mProxy(NULL)
      mProxy(NULL),
      mPortId(AUDIO_PORT_HANDLE_NONE)
{
    (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
            uid, pid, pAttributes, selectedDeviceId);
}
@@ -149,11 +151,6 @@ status_t AudioRecord::set(
        const audio_attributes_t* pAttributes,
        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, "
          "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
          "uid %d, pid %d",
@@ -173,8 +170,7 @@ status_t AudioRecord::set(
    case TRANSFER_CALLBACK:
        if (cbf == NULL) {
            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
            status = BAD_VALUE;
            goto exit;
            return BAD_VALUE;
        }
        break;
    case TRANSFER_OBTAIN:
@@ -182,16 +178,14 @@ status_t AudioRecord::set(
        break;
    default:
        ALOGE("Invalid transfer type %d", transferType);
        status = BAD_VALUE;
        goto exit;
        return BAD_VALUE;
    }
    mTransfer = transferType;

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

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

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

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

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

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

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

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

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

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

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

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

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

// must be called with mLock held
status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
{
    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) {
        ALOGE("Could not get audioflinger");
        status = NO_INIT;
        goto exit;
        return NO_INIT;
    }

    audio_io_handle_t input;

    // 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.

    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,
    // 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.
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
        bool useCaseAllowed =
@@ -586,41 +622,66 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String
        if (!useCaseAllowed) {
            ALOGW("AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
                  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 |
                    AUDIO_INPUT_FLAG_RAW));
            AudioSystem::releaseInput(input, mSessionId);
            continue;   // retry
        }
    }

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

    audio_input_flags_t flags = mFlags;

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

    input.flags = mFlags;
    // The notification frame count is the period between callbacks, as suggested by the client
    // 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;
    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
                                // but we will still need the original value also
    audio_session_t originalSessionId = mSessionId;

    record = audioFlinger->createRecord(input,
                                                              output,
                                                              &status);
    sp<IMemory> iMem;           // for cblk
    sp<IMemory> bufferMem;
    sp<media::IAudioRecord> record = audioFlinger->openRecord(input,
                                                              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) {
        ALOGE("AudioFlinger could not create record track, status: %d", status);
        goto exit;
        break;
    }
    ALOG_ASSERT(record != 0);

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

    mAwaitBoost = false;
    if (output.flags & AUDIO_INPUT_FLAG_FAST) {
        ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu",
              mReqFrameCount, output.frameCount);
    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
        if (flags & AUDIO_INPUT_FLAG_FAST) {
            ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", frameCount, temp);
            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 = output.flags;
    mRoutedDeviceId = output.selectedDeviceId;
    mSessionId = output.sessionId;
    mSampleRate = output.sampleRate;
    mFlags = flags;

    if (output.cblk == 0) {
    if (iMem == 0) {
        ALOGE("Could not get control block");
        status = NO_INIT;
        goto exit;
        return NO_INIT;
    }
    iMemPointer = output.cblk ->pointer();
    void *iMemPointer = iMem->pointer();
    if (iMemPointer == NULL) {
        ALOGE("Could not get control block pointer");
        status = NO_INIT;
        goto exit;
        return NO_INIT;
    }
    cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
    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 (output.buffers == 0) {
    if (bufferMem == 0) {
        buffers = cblk + 1;
    } else {
        buffers = output.buffers->pointer();
        buffers = bufferMem->pointer();
        if (buffers == NULL) {
            ALOGE("Could not get buffer pointer");
            status = NO_INIT;
            goto exit;
            return NO_INIT;
        }
    }

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

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

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


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

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

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

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

exit:
    mStatus = status;
    // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
    return NO_ERROR;

    // End of retry loop.
    // 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;
}

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

    mFlags = mOrigFlags;

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

File changed.

Preview size limit exceeded, changes collapsed.

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

package android.media;

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

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

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

namespace android {

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

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

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

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

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

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

};

Loading