Loading media/libaudioclient/AudioRecord.cpp +174 −104 Original line number Original line Diff line number Diff line Loading @@ -69,7 +69,8 @@ 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) { { } } Loading @@ -96,9 +97,10 @@ 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) { { (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, mStatus = 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); } } Loading Loading @@ -149,11 +151,6 @@ 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", Loading @@ -173,8 +170,7 @@ 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"); status = BAD_VALUE; return BAD_VALUE; goto exit; } } break; break; case TRANSFER_OBTAIN: case TRANSFER_OBTAIN: Loading @@ -182,16 +178,14 @@ status_t AudioRecord::set( break; break; default: default: ALOGE("Invalid transfer type %d", transferType); ALOGE("Invalid transfer type %d", transferType); status = BAD_VALUE; return 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"); status = INVALID_OPERATION; return INVALID_OPERATION; goto exit; } } if (pAttributes == NULL) { if (pAttributes == NULL) { Loading @@ -215,18 +209,16 @@ 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); status = BAD_VALUE; return 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); status = BAD_VALUE; return BAD_VALUE; goto exit; } } mChannelMask = channelMask; mChannelMask = channelMask; channelCount = audio_channel_count_from_in_mask(channelMask); uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); mChannelCount = channelCount; mChannelCount = channelCount; if (audio_is_linear_pcm(format)) { if (audio_is_linear_pcm(format)) { Loading @@ -235,24 +227,28 @@ status_t AudioRecord::set( mFrameSize = sizeof(uint8_t); mFrameSize = sizeof(uint8_t); } } // mFrameCount is initialized in createRecord_l // mFrameCount is initialized in openRecord_l mReqFrameCount = frameCount; mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; 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; mSessionId = sessionId; } ALOGV("set(): mSessionId %d", mSessionId); ALOGV("set(): mSessionId %d", mSessionId); callingPid = IPCThreadState::self()->getCallingPid(); int callingpid = IPCThreadState::self()->getCallingPid(); myPid = getpid(); int 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; } } Loading @@ -267,7 +263,7 @@ status_t AudioRecord::set( } } // create the IAudioRecord // create the IAudioRecord status = createRecord_l(0 /*epoch*/, mOpPackageName); status_t status = openRecord_l(0 /*epoch*/, mOpPackageName); if (status != NO_ERROR) { if (status != NO_ERROR) { if (mAudioRecordThread != 0) { if (mAudioRecordThread != 0) { Loading @@ -275,9 +271,10 @@ status_t AudioRecord::set( mAudioRecordThread->requestExitAndWait(); mAudioRecordThread->requestExitAndWait(); mAudioRecordThread.clear(); mAudioRecordThread.clear(); } } goto exit; return status; } } 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; Loading @@ -292,9 +289,7 @@ status_t AudioRecord::set( mFramesRead = 0; mFramesRead = 0; mFramesReadServerOffset = 0; mFramesReadServerOffset = 0; exit: return NO_ERROR; mStatus = status; return status; } } // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- Loading Loading @@ -545,29 +540,70 @@ const char * AudioRecord::convertTransferToText(transfer_type transferType) { } } // must be called with mLock held // 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(); 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"); status = NO_INIT; return 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 = Loading @@ -586,41 +622,66 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String 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 } } } } input.attr = mAttributes; // The notification frame count is the period between callbacks, as suggested by the client input.config.sample_rate = mSampleRate; // but moderated by the server. For record, the calculations are done entirely on server side. input.config.channel_mask = mChannelMask; size_t notificationFrames = mNotificationFramesReq; input.config.format = mFormat; size_t frameCount = mReqFrameCount; input.clientInfo.clientUid = mClientUid; input.clientInfo.clientPid = mClientPid; audio_input_flags_t flags = mFlags; 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) { input.clientInfo.clientTid = mAudioRecordThread->getTid(); tid = mAudioRecordThread->getTid(); } } } } input.opPackageName = opPackageName; input.flags = mFlags; size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // The notification frame count is the period between callbacks, as suggested by the client // but we will still need the original value also // but moderated by the server. For record, the calculations are done entirely on server side. audio_session_t originalSessionId = mSessionId; input.frameCount = mReqFrameCount; input.notificationFrameCount = mNotificationFramesReq; input.selectedDeviceId = mSelectedDeviceId; input.sessionId = mSessionId; originalSessionId = mSessionId; record = audioFlinger->createRecord(input, sp<IMemory> iMem; // for cblk output, sp<IMemory> bufferMem; &status); sp<media::IAudioRecord> record = audioFlinger->openRecord(input, mSampleRate, mFormat, mChannelMask, opPackageName, &temp, &flags, mClientPid, tid, mClientUid, &mSessionId, ¬ificationFrames, 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); goto exit; break; } } ALOG_ASSERT(record != 0); ALOG_ASSERT(record != 0); Loading @@ -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. // so we are no longer responsible for releasing it. mAwaitBoost = false; mAwaitBoost = false; if (output.flags & AUDIO_INPUT_FLAG_FAST) { if (mFlags & AUDIO_INPUT_FLAG_FAST) { ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", if (flags & AUDIO_INPUT_FLAG_FAST) { mReqFrameCount, output.frameCount); ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", frameCount, temp); 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 = output.flags; mFlags = flags; mRoutedDeviceId = output.selectedDeviceId; mSessionId = output.sessionId; mSampleRate = output.sampleRate; if (output.cblk == 0) { if (iMem == 0) { ALOGE("Could not get control block"); ALOGE("Could not get control block"); status = NO_INIT; return NO_INIT; goto exit; } } iMemPointer = output.cblk ->pointer(); void *iMemPointer = iMem->pointer(); if (iMemPointer == NULL) { if (iMemPointer == NULL) { ALOGE("Could not get control block pointer"); ALOGE("Could not get control block pointer"); status = NO_INIT; return NO_INIT; goto exit; } } 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. // 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 (output.buffers == 0) { if (bufferMem == 0) { buffers = cblk + 1; buffers = cblk + 1; } else { } else { buffers = output.buffers->pointer(); buffers = bufferMem->pointer(); if (buffers == NULL) { if (buffers == NULL) { ALOGE("Could not get buffer pointer"); ALOGE("Could not get buffer pointer"); status = NO_INIT; return NO_INIT; goto exit; } } } } Loading @@ -672,42 +733,43 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String mDeathNotifier.clear(); mDeathNotifier.clear(); } } mAudioRecord = record; mAudioRecord = record; mCblkMemory = output.cblk; mCblkMemory = iMem; mBufferMemory = output.buffers; mBufferMemory = bufferMem; IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands(); mCblk = cblk; mCblk = cblk; // note that output.frameCount is the (possibly revised) value of mReqFrameCount // note that temp is the (possibly revised) value of frameCount if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) { if (temp < frameCount || (frameCount == 0 && temp == 0)) { ALOGW("Requested frameCount %zu but received frameCount %zu", ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp); 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 && output.notificationFrameCount != mNotificationFramesReq) { if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) { ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu", 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 //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) { if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); 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 // We retain a copy of the I/O handle, but don't own the reference mInput = output.inputId; mInput = input; mRefreshRemaining = true; mRefreshRemaining = true; mFrameCount = output.frameCount; mFrameCount = 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 (mFrameCount > mReqFrameCount) { if (frameCount > mReqFrameCount) { mReqFrameCount = mFrameCount; mReqFrameCount = frameCount; } } // update proxy // update proxy Loading @@ -718,9 +780,17 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String mDeathNotifier = new DeathNotifier(this); mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); exit: return NO_ERROR; mStatus = status; // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger // 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; return status; } } Loading Loading @@ -1152,12 +1222,12 @@ status_t AudioRecord::restoreRecord_l(const char *from) mFlags = mOrigFlags; 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. // 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 = createRecord_l(position, mOpPackageName); status_t result = openRecord_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 Loading media/libaudioclient/IAudioFlinger.cpp +117 −46 File changed.Preview size limit exceeded, changes collapsed. Show changes media/libaudioclient/aidl/android/media/IAudioRecord.aidl +0 −1 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,6 @@ 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 Loading media/libaudioclient/include/media/AudioClient.h +3 −4 Original line number Original line Diff line number Diff line Loading @@ -19,13 +19,12 @@ #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 : public Parcelable { class AudioClient { public: public: AudioClient() : AudioClient() : clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {} clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {} Loading @@ -35,7 +34,7 @@ class AudioClient : public Parcelable { pid_t clientTid; pid_t clientTid; String16 packageName; String16 packageName; status_t readFromParcel(const Parcel *parcel) override { status_t readFromParcel(Parcel *parcel) { clientUid = parcel->readInt32(); clientUid = parcel->readInt32(); clientPid = parcel->readInt32(); clientPid = parcel->readInt32(); clientTid = parcel->readInt32(); clientTid = parcel->readInt32(); Loading @@ -43,7 +42,7 @@ class AudioClient : public Parcelable { return NO_ERROR; return NO_ERROR; } } status_t writeToParcel(Parcel *parcel) const override { status_t writeToParcel(Parcel *parcel) const { parcel->writeInt32(clientUid); parcel->writeInt32(clientUid); parcel->writeInt32(clientPid); parcel->writeInt32(clientPid); parcel->writeInt32(clientTid); parcel->writeInt32(clientTid); Loading media/libaudioclient/include/media/AudioRecord.h +2 −1 Original line number Original line Diff line number Diff line Loading @@ -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 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' // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreRecord_l(const char *from); status_t restoreRecord_l(const char *from); Loading Loading @@ -682,6 +682,7 @@ 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 Loading
media/libaudioclient/AudioRecord.cpp +174 −104 Original line number Original line Diff line number Diff line Loading @@ -69,7 +69,8 @@ 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) { { } } Loading @@ -96,9 +97,10 @@ 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) { { (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, mStatus = 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); } } Loading Loading @@ -149,11 +151,6 @@ 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", Loading @@ -173,8 +170,7 @@ 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"); status = BAD_VALUE; return BAD_VALUE; goto exit; } } break; break; case TRANSFER_OBTAIN: case TRANSFER_OBTAIN: Loading @@ -182,16 +178,14 @@ status_t AudioRecord::set( break; break; default: default: ALOGE("Invalid transfer type %d", transferType); ALOGE("Invalid transfer type %d", transferType); status = BAD_VALUE; return 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"); status = INVALID_OPERATION; return INVALID_OPERATION; goto exit; } } if (pAttributes == NULL) { if (pAttributes == NULL) { Loading @@ -215,18 +209,16 @@ 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); status = BAD_VALUE; return 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); status = BAD_VALUE; return BAD_VALUE; goto exit; } } mChannelMask = channelMask; mChannelMask = channelMask; channelCount = audio_channel_count_from_in_mask(channelMask); uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); mChannelCount = channelCount; mChannelCount = channelCount; if (audio_is_linear_pcm(format)) { if (audio_is_linear_pcm(format)) { Loading @@ -235,24 +227,28 @@ status_t AudioRecord::set( mFrameSize = sizeof(uint8_t); mFrameSize = sizeof(uint8_t); } } // mFrameCount is initialized in createRecord_l // mFrameCount is initialized in openRecord_l mReqFrameCount = frameCount; mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; 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; mSessionId = sessionId; } ALOGV("set(): mSessionId %d", mSessionId); ALOGV("set(): mSessionId %d", mSessionId); callingPid = IPCThreadState::self()->getCallingPid(); int callingpid = IPCThreadState::self()->getCallingPid(); myPid = getpid(); int 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; } } Loading @@ -267,7 +263,7 @@ status_t AudioRecord::set( } } // create the IAudioRecord // create the IAudioRecord status = createRecord_l(0 /*epoch*/, mOpPackageName); status_t status = openRecord_l(0 /*epoch*/, mOpPackageName); if (status != NO_ERROR) { if (status != NO_ERROR) { if (mAudioRecordThread != 0) { if (mAudioRecordThread != 0) { Loading @@ -275,9 +271,10 @@ status_t AudioRecord::set( mAudioRecordThread->requestExitAndWait(); mAudioRecordThread->requestExitAndWait(); mAudioRecordThread.clear(); mAudioRecordThread.clear(); } } goto exit; return status; } } 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; Loading @@ -292,9 +289,7 @@ status_t AudioRecord::set( mFramesRead = 0; mFramesRead = 0; mFramesReadServerOffset = 0; mFramesReadServerOffset = 0; exit: return NO_ERROR; mStatus = status; return status; } } // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- Loading Loading @@ -545,29 +540,70 @@ const char * AudioRecord::convertTransferToText(transfer_type transferType) { } } // must be called with mLock held // 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(); 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"); status = NO_INIT; return 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 = Loading @@ -586,41 +622,66 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String 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 } } } } input.attr = mAttributes; // The notification frame count is the period between callbacks, as suggested by the client input.config.sample_rate = mSampleRate; // but moderated by the server. For record, the calculations are done entirely on server side. input.config.channel_mask = mChannelMask; size_t notificationFrames = mNotificationFramesReq; input.config.format = mFormat; size_t frameCount = mReqFrameCount; input.clientInfo.clientUid = mClientUid; input.clientInfo.clientPid = mClientPid; audio_input_flags_t flags = mFlags; 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) { input.clientInfo.clientTid = mAudioRecordThread->getTid(); tid = mAudioRecordThread->getTid(); } } } } input.opPackageName = opPackageName; input.flags = mFlags; size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, // The notification frame count is the period between callbacks, as suggested by the client // but we will still need the original value also // but moderated by the server. For record, the calculations are done entirely on server side. audio_session_t originalSessionId = mSessionId; input.frameCount = mReqFrameCount; input.notificationFrameCount = mNotificationFramesReq; input.selectedDeviceId = mSelectedDeviceId; input.sessionId = mSessionId; originalSessionId = mSessionId; record = audioFlinger->createRecord(input, sp<IMemory> iMem; // for cblk output, sp<IMemory> bufferMem; &status); sp<media::IAudioRecord> record = audioFlinger->openRecord(input, mSampleRate, mFormat, mChannelMask, opPackageName, &temp, &flags, mClientPid, tid, mClientUid, &mSessionId, ¬ificationFrames, 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); goto exit; break; } } ALOG_ASSERT(record != 0); ALOG_ASSERT(record != 0); Loading @@ -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. // so we are no longer responsible for releasing it. mAwaitBoost = false; mAwaitBoost = false; if (output.flags & AUDIO_INPUT_FLAG_FAST) { if (mFlags & AUDIO_INPUT_FLAG_FAST) { ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", if (flags & AUDIO_INPUT_FLAG_FAST) { mReqFrameCount, output.frameCount); ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", frameCount, temp); 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 = output.flags; mFlags = flags; mRoutedDeviceId = output.selectedDeviceId; mSessionId = output.sessionId; mSampleRate = output.sampleRate; if (output.cblk == 0) { if (iMem == 0) { ALOGE("Could not get control block"); ALOGE("Could not get control block"); status = NO_INIT; return NO_INIT; goto exit; } } iMemPointer = output.cblk ->pointer(); void *iMemPointer = iMem->pointer(); if (iMemPointer == NULL) { if (iMemPointer == NULL) { ALOGE("Could not get control block pointer"); ALOGE("Could not get control block pointer"); status = NO_INIT; return NO_INIT; goto exit; } } 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. // 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 (output.buffers == 0) { if (bufferMem == 0) { buffers = cblk + 1; buffers = cblk + 1; } else { } else { buffers = output.buffers->pointer(); buffers = bufferMem->pointer(); if (buffers == NULL) { if (buffers == NULL) { ALOGE("Could not get buffer pointer"); ALOGE("Could not get buffer pointer"); status = NO_INIT; return NO_INIT; goto exit; } } } } Loading @@ -672,42 +733,43 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String mDeathNotifier.clear(); mDeathNotifier.clear(); } } mAudioRecord = record; mAudioRecord = record; mCblkMemory = output.cblk; mCblkMemory = iMem; mBufferMemory = output.buffers; mBufferMemory = bufferMem; IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands(); mCblk = cblk; mCblk = cblk; // note that output.frameCount is the (possibly revised) value of mReqFrameCount // note that temp is the (possibly revised) value of frameCount if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) { if (temp < frameCount || (frameCount == 0 && temp == 0)) { ALOGW("Requested frameCount %zu but received frameCount %zu", ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp); 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 && output.notificationFrameCount != mNotificationFramesReq) { if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) { ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu", 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 //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) { if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); 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 // We retain a copy of the I/O handle, but don't own the reference mInput = output.inputId; mInput = input; mRefreshRemaining = true; mRefreshRemaining = true; mFrameCount = output.frameCount; mFrameCount = 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 (mFrameCount > mReqFrameCount) { if (frameCount > mReqFrameCount) { mReqFrameCount = mFrameCount; mReqFrameCount = frameCount; } } // update proxy // update proxy Loading @@ -718,9 +780,17 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String mDeathNotifier = new DeathNotifier(this); mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); exit: return NO_ERROR; mStatus = status; // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger // 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; return status; } } Loading Loading @@ -1152,12 +1222,12 @@ status_t AudioRecord::restoreRecord_l(const char *from) mFlags = mOrigFlags; 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. // 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 = createRecord_l(position, mOpPackageName); status_t result = openRecord_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 Loading
media/libaudioclient/IAudioFlinger.cpp +117 −46 File changed.Preview size limit exceeded, changes collapsed. Show changes
media/libaudioclient/aidl/android/media/IAudioRecord.aidl +0 −1 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,6 @@ 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 Loading
media/libaudioclient/include/media/AudioClient.h +3 −4 Original line number Original line Diff line number Diff line Loading @@ -19,13 +19,12 @@ #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 : public Parcelable { class AudioClient { public: public: AudioClient() : AudioClient() : clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {} clientUid(-1), clientPid(-1), clientTid(-1), packageName("") {} Loading @@ -35,7 +34,7 @@ class AudioClient : public Parcelable { pid_t clientTid; pid_t clientTid; String16 packageName; String16 packageName; status_t readFromParcel(const Parcel *parcel) override { status_t readFromParcel(Parcel *parcel) { clientUid = parcel->readInt32(); clientUid = parcel->readInt32(); clientPid = parcel->readInt32(); clientPid = parcel->readInt32(); clientTid = parcel->readInt32(); clientTid = parcel->readInt32(); Loading @@ -43,7 +42,7 @@ class AudioClient : public Parcelable { return NO_ERROR; return NO_ERROR; } } status_t writeToParcel(Parcel *parcel) const override { status_t writeToParcel(Parcel *parcel) const { parcel->writeInt32(clientUid); parcel->writeInt32(clientUid); parcel->writeInt32(clientPid); parcel->writeInt32(clientPid); parcel->writeInt32(clientTid); parcel->writeInt32(clientTid); Loading
media/libaudioclient/include/media/AudioRecord.h +2 −1 Original line number Original line Diff line number Diff line Loading @@ -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 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' // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreRecord_l(const char *from); status_t restoreRecord_l(const char *from); Loading Loading @@ -682,6 +682,7 @@ 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