Merge changes Ia0217951,Ie8293036,Ic359e977,I9d939d17
* changes:
audiopolicy: Refactor AudioPolicyManager::updateCallRouting
audiopolicy: Remove ; after namespace bracket
audiopolicy: Use C++11 atomics, factor out handle generation
audiopolicy: Make fields of HwModule private
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 741d084..2432cac 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -69,7 +69,8 @@
: 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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
- mSessionId = sessionId;
+ 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 @@
}
// 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 @@
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 @@
mFramesRead = 0;
mFramesReadServerOffset = 0;
-exit:
- mStatus = status;
- return status;
+ return NO_ERROR;
}
// -------------------------------------------------------------------------
@@ -545,29 +540,70 @@
}
// 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 @@
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;
- if (mFlags & AUDIO_INPUT_FLAG_FAST) {
- if (mAudioRecordThread != 0) {
- input.clientInfo.clientTid = 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 notificationFrames = mNotificationFramesReq;
+ size_t frameCount = mReqFrameCount;
- record = audioFlinger->createRecord(input,
- output,
- &status);
+ audio_input_flags_t flags = mFlags;
+
+ pid_t tid = -1;
+ if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+ if (mAudioRecordThread != 0) {
+ tid = mAudioRecordThread->getTid();
+ }
+ }
+
+ 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;
+
+ 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,
+ ¬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) {
ALOGE("AudioFlinger could not create record track, status: %d", status);
- goto exit;
+ break;
}
ALOG_ASSERT(record != 0);
@@ -628,41 +689,41 @@
// 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);
- mAwaitBoost = true;
+ 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 @@
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 @@
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 @@
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
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 56ddd4f..5cf2bdb 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -22,7 +22,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include "IAudioFlinger.h"
@@ -31,7 +30,7 @@
enum {
CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
- CREATE_RECORD,
+ OPEN_RECORD,
SAMPLE_RATE,
RESERVED, // obsolete, was CHANNEL_COUNT
FORMAT,
@@ -131,39 +130,102 @@
return track;
}
- virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
- CreateRecordOutput& output,
- status_t *status)
+ virtual sp<media::IAudioRecord> openRecord(
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ const String16& opPackageName,
+ size_t *pFrameCount,
+ audio_input_flags_t *flags,
+ pid_t pid,
+ pid_t tid,
+ int clientUid,
+ audio_session_t *sessionId,
+ size_t *notificationFrames,
+ sp<IMemory>& cblk,
+ sp<IMemory>& buffers,
+ status_t *status,
+ audio_port_handle_t portId)
{
Parcel data, reply;
sp<media::IAudioRecord> record;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-
- if (status == nullptr) {
- return record;
+ data.writeInt32((int32_t) input);
+ data.writeInt32(sampleRate);
+ data.writeInt32(format);
+ data.writeInt32(channelMask);
+ data.writeString16(opPackageName);
+ size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0;
+ data.writeInt64(frameCount);
+ audio_input_flags_t lFlags = flags != NULL ? *flags : AUDIO_INPUT_FLAG_NONE;
+ data.writeInt32(lFlags);
+ data.writeInt32((int32_t) pid);
+ data.writeInt32((int32_t) tid);
+ data.writeInt32((int32_t) clientUid);
+ audio_session_t lSessionId = AUDIO_SESSION_ALLOCATE;
+ if (sessionId != NULL) {
+ lSessionId = *sessionId;
}
-
- input.writeToParcel(&data);
-
- status_t lStatus = remote()->transact(CREATE_RECORD, data, &reply);
+ data.writeInt32(lSessionId);
+ data.writeInt64(notificationFrames != NULL ? *notificationFrames : 0);
+ data.writeInt32(portId);
+ cblk.clear();
+ buffers.clear();
+ status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply);
if (lStatus != NO_ERROR) {
- ALOGE("createRecord transaction error %d", lStatus);
- *status = DEAD_OBJECT;
- return record;
+ ALOGE("openRecord error: %s", strerror(-lStatus));
+ } else {
+ frameCount = reply.readInt64();
+ if (pFrameCount != NULL) {
+ *pFrameCount = frameCount;
+ }
+ lFlags = (audio_input_flags_t)reply.readInt32();
+ if (flags != NULL) {
+ *flags = lFlags;
+ }
+ lSessionId = (audio_session_t) reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
+ size_t lNotificationFrames = (size_t) reply.readInt64();
+ if (notificationFrames != NULL) {
+ *notificationFrames = lNotificationFrames;
+ }
+ lStatus = reply.readInt32();
+ record = interface_cast<media::IAudioRecord>(reply.readStrongBinder());
+ cblk = interface_cast<IMemory>(reply.readStrongBinder());
+ if (cblk != 0 && cblk->pointer() == NULL) {
+ cblk.clear();
+ }
+ buffers = interface_cast<IMemory>(reply.readStrongBinder());
+ if (buffers != 0 && buffers->pointer() == NULL) {
+ buffers.clear();
+ }
+ if (lStatus == NO_ERROR) {
+ if (record == 0) {
+ ALOGE("openRecord should have returned an IAudioRecord");
+ lStatus = UNKNOWN_ERROR;
+ } else if (cblk == 0) {
+ ALOGE("openRecord should have returned a cblk");
+ lStatus = NO_MEMORY;
+ }
+ // buffers is permitted to be 0
+ } else {
+ if (record != 0 || cblk != 0 || buffers != 0) {
+ ALOGE("openRecord returned an IAudioRecord, cblk, "
+ "or buffers but with status %d", lStatus);
+ }
+ }
+ if (lStatus != NO_ERROR) {
+ record.clear();
+ cblk.clear();
+ buffers.clear();
+ }
}
- *status = reply.readInt32();
- if (*status != NO_ERROR) {
- ALOGE("createRecord returned error %d", *status);
- return record;
+ if (status != NULL) {
+ *status = lStatus;
}
-
- record = interface_cast<media::IAudioRecord>(reply.readStrongBinder());
- if (record == 0) {
- ALOGE("createRecord returned a NULL IAudioRecord with status OK");
- *status = DEAD_OBJECT;
- return record;
- }
- output.readFromParcel(&reply);
return record;
}
@@ -837,46 +899,21 @@
status_t BnAudioFlinger::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
- // make sure transactions reserved to AudioPolicyManager do not come from other processes
- switch (code) {
- case SET_STREAM_VOLUME:
- case SET_STREAM_MUTE:
- case SET_MODE:
- case OPEN_OUTPUT:
- case OPEN_DUPLICATE_OUTPUT:
- case CLOSE_OUTPUT:
- case SUSPEND_OUTPUT:
- case RESTORE_OUTPUT:
- case OPEN_INPUT:
- case CLOSE_INPUT:
- case INVALIDATE_STREAM:
- case SET_VOICE_VOLUME:
- case MOVE_EFFECTS:
- case LOAD_HW_MODULE:
- case LIST_AUDIO_PORTS:
- case GET_AUDIO_PORT:
- case CREATE_AUDIO_PATCH:
- case RELEASE_AUDIO_PATCH:
- case LIST_AUDIO_PATCHES:
- case SET_AUDIO_PORT_CONFIG:
- ALOGW("%s: transaction %d received from PID %d",
- __func__, code, IPCThreadState::self()->getCallingPid());
- return INVALID_OPERATION;
- default:
- break;
- }
-
// Whitelist of relevant events to trigger log merging.
// Log merging should activate during audio activity of any kind. This are considered the
// most relevant events.
// TODO should select more wisely the items from the list
switch (code) {
case CREATE_TRACK:
- case CREATE_RECORD:
+ case OPEN_RECORD:
case SET_MASTER_VOLUME:
case SET_MASTER_MUTE:
+ case SET_STREAM_VOLUME:
+ case SET_STREAM_MUTE:
case SET_MIC_MUTE:
case SET_PARAMETERS:
+ case OPEN_INPUT:
+ case SET_VOICE_VOLUME:
case CREATE_EFFECT:
case SYSTEM_READY: {
requestLogMerge();
@@ -885,7 +922,6 @@
default:
break;
}
-
switch (code) {
case CREATE_TRACK: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
@@ -912,29 +948,37 @@
output.writeToParcel(reply);
return NO_ERROR;
} break;
- case CREATE_RECORD: {
+ case OPEN_RECORD: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
-
- CreateRecordInput input;
- if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
- reply->writeInt32(DEAD_OBJECT);
- return NO_ERROR;
- }
-
- status_t status;
- CreateRecordOutput output;
-
- sp<media::IAudioRecord> record = createRecord(input,
- output,
- &status);
-
+ audio_io_handle_t input = (audio_io_handle_t) data.readInt32();
+ uint32_t sampleRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ audio_channel_mask_t channelMask = data.readInt32();
+ const String16& opPackageName = data.readString16();
+ size_t frameCount = data.readInt64();
+ audio_input_flags_t flags = (audio_input_flags_t) data.readInt32();
+ pid_t pid = (pid_t) data.readInt32();
+ pid_t tid = (pid_t) data.readInt32();
+ int clientUid = data.readInt32();
+ audio_session_t sessionId = (audio_session_t) data.readInt32();
+ size_t notificationFrames = data.readInt64();
+ audio_port_handle_t portId = (audio_port_handle_t) data.readInt32();
+ sp<IMemory> cblk;
+ sp<IMemory> buffers;
+ status_t status = NO_ERROR;
+ sp<media::IAudioRecord> record = openRecord(input,
+ sampleRate, format, channelMask, opPackageName, &frameCount, &flags,
+ pid, tid, clientUid, &sessionId, ¬ificationFrames, cblk, buffers,
+ &status, portId);
LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR));
+ reply->writeInt64(frameCount);
+ reply->writeInt32(flags);
+ reply->writeInt32(sessionId);
+ reply->writeInt64(notificationFrames);
reply->writeInt32(status);
- if (status != NO_ERROR) {
- return NO_ERROR;
- }
reply->writeStrongBinder(IInterface::asBinder(record));
- output.writeToParcel(reply);
+ reply->writeStrongBinder(IInterface::asBinder(cblk));
+ reply->writeStrongBinder(IInterface::asBinder(buffers));
return NO_ERROR;
} break;
case SAMPLE_RATE: {
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 53bc1b7..970ae90 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -22,7 +22,6 @@
#include <math.h>
#include <sys/types.h>
-#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <media/AudioEffect.h>
@@ -832,33 +831,10 @@
// ----------------------------------------------------------------------
+
status_t BnAudioPolicyService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
- // make sure transactions reserved to AudioFlinger do not come from other processes
- switch (code) {
- case START_OUTPUT:
- case STOP_OUTPUT:
- case RELEASE_OUTPUT:
- case GET_INPUT_FOR_ATTR:
- case START_INPUT:
- case STOP_INPUT:
- case RELEASE_INPUT:
- case GET_STRATEGY_FOR_STREAM:
- case GET_OUTPUT_FOR_EFFECT:
- case REGISTER_EFFECT:
- case UNREGISTER_EFFECT:
- case SET_EFFECT_ENABLED:
- case GET_OUTPUT_FOR_ATTR:
- case ACQUIRE_SOUNDTRIGGER_SESSION:
- case RELEASE_SOUNDTRIGGER_SESSION:
- ALOGW("%s: transaction %d received from PID %d",
- __func__, code, IPCThreadState::self()->getCallingPid());
- return INVALID_OPERATION;
- default:
- break;
- }
-
switch (code) {
case SET_DEVICE_CONNECTION_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index 7572671..50ce78f 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -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
diff --git a/media/libaudioclient/include/media/AudioClient.h b/media/libaudioclient/include/media/AudioClient.h
index 247af9e..108e326 100644
--- a/media/libaudioclient/include/media/AudioClient.h
+++ b/media/libaudioclient/include/media/AudioClient.h
@@ -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 @@
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 @@
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);
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index 00c2a88..51596a2 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -570,7 +570,7 @@
// 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 @@
// 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
};
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 24a6e22..66601da 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -231,7 +231,7 @@
audio_stream_type_t stream,
audio_session_t session);
- // Client must successfully hand off the handle reference to AudioFlinger via createRecord(),
+ // Client must successfully hand off the handle reference to AudioFlinger via openRecord(),
// or release it with releaseInput().
static status_t getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 57d9778..9061c26 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -25,7 +25,6 @@
#include <utils/Errors.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
#include <media/AudioClient.h>
#include <media/IAudioTrack.h>
#include <media/IAudioFlingerClient.h>
@@ -51,9 +50,9 @@
* when calling createTrack() including arguments that will be updated by AudioFlinger
* and returned in CreateTrackOutput object
*/
- class CreateTrackInput : public Parcelable {
+ class CreateTrackInput {
public:
- status_t readFromParcel(const Parcel *parcel) override {
+ status_t readFromParcel(Parcel *parcel) {
/* input arguments*/
memset(&attr, 0, sizeof(audio_attributes_t));
if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
@@ -64,9 +63,7 @@
if (parcel->read(&config, sizeof(audio_config_t)) != NO_ERROR) {
return DEAD_OBJECT;
}
- if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
- return DEAD_OBJECT;
- }
+ (void)clientInfo.readFromParcel(parcel);
if (parcel->readInt32() != 0) {
sharedBuffer = interface_cast<IMemory>(parcel->readStrongBinder());
if (sharedBuffer == 0 || sharedBuffer->pointer() == NULL) {
@@ -85,7 +82,7 @@
return NO_ERROR;
}
- status_t writeToParcel(Parcel *parcel) const override {
+ status_t writeToParcel(Parcel *parcel) const {
/* input arguments*/
(void)parcel->write(&attr, sizeof(audio_attributes_t));
(void)parcel->write(&config, sizeof(audio_config_t));
@@ -128,9 +125,9 @@
* when calling createTrack() including arguments that were passed as I/O for update by
* CreateTrackInput.
*/
- class CreateTrackOutput : public Parcelable {
+ class CreateTrackOutput {
public:
- status_t readFromParcel(const Parcel *parcel) override {
+ status_t readFromParcel(Parcel *parcel) {
/* input/output arguments*/
(void)parcel->read(&flags, sizeof(audio_output_flags_t));
frameCount = parcel->readInt64();
@@ -147,7 +144,7 @@
return NO_ERROR;
}
- status_t writeToParcel(Parcel *parcel) const override {
+ status_t writeToParcel(Parcel *parcel) const {
/* input/output arguments*/
(void)parcel->write(&flags, sizeof(audio_output_flags_t));
(void)parcel->writeInt64(frameCount);
@@ -179,140 +176,6 @@
audio_io_handle_t outputId;
};
- /* CreateRecordInput contains all input arguments sent by AudioRecord to AudioFlinger
- * when calling createRecord() including arguments that will be updated by AudioFlinger
- * and returned in CreateRecordOutput object
- */
- class CreateRecordInput : public Parcelable {
- public:
- status_t readFromParcel(const Parcel *parcel) override {
- /* input arguments*/
- memset(&attr, 0, sizeof(audio_attributes_t));
- if (parcel->read(&attr, sizeof(audio_attributes_t)) != NO_ERROR) {
- return DEAD_OBJECT;
- }
- attr.tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE -1] = '\0';
- memset(&config, 0, sizeof(audio_config_base_t));
- if (parcel->read(&config, sizeof(audio_config_base_t)) != NO_ERROR) {
- return DEAD_OBJECT;
- }
- if (clientInfo.readFromParcel(parcel) != NO_ERROR) {
- return DEAD_OBJECT;
- }
- opPackageName = parcel->readString16();
-
- /* input/output arguments*/
- (void)parcel->read(&flags, sizeof(audio_input_flags_t));
- frameCount = parcel->readInt64();
- notificationFrameCount = parcel->readInt64();
- (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
- (void)parcel->read(&sessionId, sizeof(audio_session_t));
- return NO_ERROR;
- }
-
- status_t writeToParcel(Parcel *parcel) const override {
- /* input arguments*/
- (void)parcel->write(&attr, sizeof(audio_attributes_t));
- (void)parcel->write(&config, sizeof(audio_config_base_t));
- (void)clientInfo.writeToParcel(parcel);
- (void)parcel->writeString16(opPackageName);
-
- /* input/output arguments*/
- (void)parcel->write(&flags, sizeof(audio_input_flags_t));
- (void)parcel->writeInt64(frameCount);
- (void)parcel->writeInt64(notificationFrameCount);
- (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
- (void)parcel->write(&sessionId, sizeof(audio_session_t));
- return NO_ERROR;
- }
-
- /* input */
- audio_attributes_t attr;
- audio_config_base_t config;
- AudioClient clientInfo;
- String16 opPackageName;
-
- /* input/output */
- audio_input_flags_t flags;
- size_t frameCount;
- size_t notificationFrameCount;
- audio_port_handle_t selectedDeviceId;
- audio_session_t sessionId;
- };
-
- /* CreateRecordOutput contains all output arguments returned by AudioFlinger to AudioRecord
- * when calling createRecord() including arguments that were passed as I/O for update by
- * CreateRecordInput.
- */
- class CreateRecordOutput : public Parcelable {
- public:
- status_t readFromParcel(const Parcel *parcel) override {
- /* input/output arguments*/
- (void)parcel->read(&flags, sizeof(audio_input_flags_t));
- frameCount = parcel->readInt64();
- notificationFrameCount = parcel->readInt64();
- (void)parcel->read(&selectedDeviceId, sizeof(audio_port_handle_t));
- (void)parcel->read(&sessionId, sizeof(audio_session_t));
-
- /* output arguments*/
- sampleRate = parcel->readUint32();
- (void)parcel->read(&inputId, sizeof(audio_io_handle_t));
- if (parcel->readInt32() != 0) {
- cblk = interface_cast<IMemory>(parcel->readStrongBinder());
- if (cblk == 0 || cblk->pointer() == NULL) {
- return BAD_VALUE;
- }
- }
- if (parcel->readInt32() != 0) {
- buffers = interface_cast<IMemory>(parcel->readStrongBinder());
- if (buffers == 0 || buffers->pointer() == NULL) {
- return BAD_VALUE;
- }
- }
- return NO_ERROR;
- }
-
- status_t writeToParcel(Parcel *parcel) const override {
- /* input/output arguments*/
- (void)parcel->write(&flags, sizeof(audio_input_flags_t));
- (void)parcel->writeInt64(frameCount);
- (void)parcel->writeInt64(notificationFrameCount);
- (void)parcel->write(&selectedDeviceId, sizeof(audio_port_handle_t));
- (void)parcel->write(&sessionId, sizeof(audio_session_t));
-
- /* output arguments*/
- (void)parcel->writeUint32(sampleRate);
- (void)parcel->write(&inputId, sizeof(audio_io_handle_t));
- if (cblk != 0) {
- (void)parcel->writeInt32(1);
- (void)parcel->writeStrongBinder(IInterface::asBinder(cblk));
- } else {
- (void)parcel->writeInt32(0);
- }
- if (buffers != 0) {
- (void)parcel->writeInt32(1);
- (void)parcel->writeStrongBinder(IInterface::asBinder(buffers));
- } else {
- (void)parcel->writeInt32(0);
- }
-
- return NO_ERROR;
- }
-
- /* input/output */
- audio_input_flags_t flags;
- size_t frameCount;
- size_t notificationFrameCount;
- audio_port_handle_t selectedDeviceId;
- audio_session_t sessionId;
-
- /* output */
- uint32_t sampleRate;
- audio_io_handle_t inputId;
- sp<IMemory> cblk;
- sp<IMemory> buffers;
- };
-
// invariant on exit for all APIs that return an sp<>:
// (return value != 0) == (*status == NO_ERROR)
@@ -323,9 +186,26 @@
CreateTrackOutput& output,
status_t *status) = 0;
- virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
- CreateRecordOutput& output,
- status_t *status) = 0;
+ virtual sp<media::IAudioRecord> openRecord(
+ // On successful return, AudioFlinger takes over the handle
+ // reference and will release it when the track is destroyed.
+ // However on failure, the client is responsible for release.
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ const String16& callingPackage,
+ size_t *pFrameCount,
+ audio_input_flags_t *flags,
+ pid_t pid,
+ pid_t tid, // -1 means unused, otherwise must be valid non-0
+ int clientUid,
+ audio_session_t *sessionId,
+ size_t *notificationFrames,
+ sp<IMemory>& cblk,
+ sp<IMemory>& buffers, // return value 0 means it follows cblk
+ status_t *status,
+ audio_port_handle_t portId) = 0;
// FIXME Surprisingly, format/latency don't work for input handles
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index aeb32bb..9cb0357 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -674,11 +674,7 @@
audio_session_t sessionId = input.sessionId;
if (sessionId == AUDIO_SESSION_ALLOCATE) {
sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
- } else if (audio_unique_id_get_use(sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
- lStatus = BAD_VALUE;
- goto Exit;
}
-
output.sessionId = sessionId;
output.outputId = AUDIO_IO_HANDLE_NONE;
output.selectedDeviceId = input.selectedDeviceId;
@@ -1572,144 +1568,120 @@
// ----------------------------------------------------------------------------
-sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& input,
- CreateRecordOutput& output,
- status_t *status)
+sp<media::IAudioRecord> AudioFlinger::openRecord(
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ const String16& opPackageName,
+ size_t *frameCount,
+ audio_input_flags_t *flags,
+ pid_t pid,
+ pid_t tid,
+ int clientUid,
+ audio_session_t *sessionId,
+ size_t *notificationFrames,
+ sp<IMemory>& cblk,
+ sp<IMemory>& buffers,
+ status_t *status,
+ audio_port_handle_t portId)
{
sp<RecordThread::RecordTrack> recordTrack;
sp<RecordHandle> recordHandle;
sp<Client> client;
status_t lStatus;
- audio_session_t sessionId = input.sessionId;
- audio_port_handle_t portId;
+ audio_session_t lSessionId;
- output.cblk.clear();
- output.buffers.clear();
+ cblk.clear();
+ buffers.clear();
- bool updatePid = (input.clientInfo.clientPid == -1);
+ bool updatePid = (pid == -1);
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
- uid_t clientUid = input.clientInfo.clientUid;
if (!isTrustedCallingUid(callingUid)) {
- ALOGW_IF(clientUid != callingUid,
- "%s uid %d tried to pass itself off as %d",
- __FUNCTION__, callingUid, clientUid);
+ ALOGW_IF((uid_t)clientUid != callingUid,
+ "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid, clientUid);
clientUid = callingUid;
updatePid = true;
}
- pid_t clientPid = input.clientInfo.clientPid;
+
if (updatePid) {
const pid_t callingPid = IPCThreadState::self()->getCallingPid();
- ALOGW_IF(clientPid != -1 && clientPid != callingPid,
+ ALOGW_IF(pid != -1 && pid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
- __func__, callingUid, callingPid, clientPid);
- clientPid = callingPid;
+ __func__, callingUid, callingPid, pid);
+ pid = callingPid;
}
// check calling permissions
- if (!recordingAllowed(input.opPackageName, input.clientInfo.clientTid, clientUid)) {
- ALOGE("createRecord() permission denied: recording not allowed");
+ if (!recordingAllowed(opPackageName, tid, clientUid)) {
+ ALOGE("openRecord() permission denied: recording not allowed");
lStatus = PERMISSION_DENIED;
goto Exit;
}
+
+ // further sample rate checks are performed by createRecordTrack_l()
+ if (sampleRate == 0) {
+ ALOGE("openRecord() invalid sample rate %u", sampleRate);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
// we don't yet support anything other than linear PCM
- if (!audio_is_valid_format(input.config.format) || !audio_is_linear_pcm(input.config.format)) {
- ALOGE("createRecord() invalid format %#x", input.config.format);
+ if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
+ ALOGE("openRecord() invalid format %#x", format);
lStatus = BAD_VALUE;
goto Exit;
}
// further channel mask checks are performed by createRecordTrack_l()
- if (!audio_is_input_channel(input.config.channel_mask)) {
- ALOGE("createRecord() invalid channel mask %#x", input.config.channel_mask);
+ if (!audio_is_input_channel(channelMask)) {
+ ALOGE("openRecord() invalid channel mask %#x", channelMask);
lStatus = BAD_VALUE;
goto Exit;
}
- if (sessionId == AUDIO_SESSION_ALLOCATE) {
- sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
- } else if (audio_unique_id_get_use(sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
- output.sessionId = sessionId;
- output.inputId = AUDIO_IO_HANDLE_NONE;
- output.selectedDeviceId = input.selectedDeviceId;
- output.flags = input.flags;
-
- client = registerPid(clientPid);
-
- // 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 via break on no error of got exit on error
- // The sp<> references will be dropped when re-entering scope.
- // The lack of indentation is deliberate, to reduce code churn and ease merges.
- for (;;) {
- lStatus = AudioSystem::getInputForAttr(&input.attr, &output.inputId,
- sessionId,
- // FIXME compare to AudioTrack
- clientPid,
- clientUid,
- &input.config,
- output.flags, &output.selectedDeviceId, &portId);
-
{
Mutex::Autolock _l(mLock);
- RecordThread *thread = checkRecordThread_l(output.inputId);
+ RecordThread *thread = checkRecordThread_l(input);
if (thread == NULL) {
- ALOGE("createRecord() checkRecordThread_l failed");
+ ALOGE("openRecord() checkRecordThread_l failed");
lStatus = BAD_VALUE;
goto Exit;
}
- ALOGV("createRecord() lSessionId: %d input %d", sessionId, output.inputId);
+ client = registerPid(pid);
- output.sampleRate = input.config.sample_rate;
- output.frameCount = input.frameCount;
- output.notificationFrameCount = input.notificationFrameCount;
+ if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
+ if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ lSessionId = *sessionId;
+ } else {
+ // if no audio session id is provided, create one here
+ lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
+ }
+ ALOGV("openRecord() lSessionId: %d input %d", lSessionId, input);
- recordTrack = thread->createRecordTrack_l(client, &output.sampleRate,
- input.config.format, input.config.channel_mask,
- &output.frameCount, sessionId,
- &output.notificationFrameCount,
- clientUid, &output.flags,
- input.clientInfo.clientTid,
- &lStatus, portId);
+ recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask,
+ frameCount, lSessionId, notificationFrames,
+ clientUid, flags, tid, &lStatus, portId);
LOG_ALWAYS_FATAL_IF((lStatus == NO_ERROR) && (recordTrack == 0));
- // lStatus == BAD_TYPE means FAST flag was rejected: request a new input from
- // audio policy manager without FAST constraint
- if (lStatus == BAD_TYPE) {
- AudioSystem::releaseInput(output.inputId, sessionId);
- recordTrack.clear();
- continue;
+ if (lStatus == NO_ERROR) {
+ // Check if one effect chain was awaiting for an AudioRecord to be created on this
+ // session and move it to this thread.
+ sp<EffectChain> chain = getOrphanEffectChain_l(lSessionId);
+ if (chain != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ thread->addEffectChain_l(chain);
+ }
}
-
- if (lStatus != NO_ERROR) {
- recordTrack.clear();
- goto Exit;
- }
-
- // Check if one effect chain was awaiting for an AudioRecord to be created on this
- // session and move it to this thread.
- sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
- if (chain != 0) {
- Mutex::Autolock _l(thread->mLock);
- thread->addEffectChain_l(chain);
- }
- break;
- }
- // End of retry loop.
- // The lack of indentation is deliberate, to reduce code churn and ease merges.
}
- output.cblk = recordTrack->getCblk();
- output.buffers = recordTrack->getBuffers();
-
- // return handle to client
- recordHandle = new RecordHandle(recordTrack);
-
-Exit:
if (lStatus != NO_ERROR) {
// remove local strong reference to Client before deleting the RecordTrack so that the
// Client destructor is called by the TrackBase destructor with mClientLock held
@@ -1719,8 +1691,17 @@
Mutex::Autolock _cl(mClientLock);
client.clear();
}
+ recordTrack.clear();
+ goto Exit;
}
+ cblk = recordTrack->getCblk();
+ buffers = recordTrack->getBuffers();
+
+ // return handle to client
+ recordHandle = new RecordHandle(recordTrack);
+
+Exit:
*status = lStatus;
return recordHandle;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index bc73ffd..506420c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -118,9 +118,23 @@
CreateTrackOutput& output,
status_t *status);
- virtual sp<media::IAudioRecord> createRecord(const CreateRecordInput& input,
- CreateRecordOutput& output,
- status_t *status);
+ virtual sp<media::IAudioRecord> openRecord(
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ const String16& opPackageName,
+ size_t *pFrameCount,
+ audio_input_flags_t *flags,
+ pid_t pid,
+ pid_t tid,
+ int clientUid,
+ audio_session_t *sessionId,
+ size_t *notificationFrames,
+ sp<IMemory>& cblk,
+ sp<IMemory>& buffers,
+ status_t *status /*non-NULL*/,
+ audio_port_handle_t portId);
virtual uint32_t sampleRate(audio_io_handle_t ioHandle) const;
virtual audio_format_t format(audio_io_handle_t output) const;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7636df6..b2a1e18 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6708,12 +6708,12 @@
// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
const sp<AudioFlinger::Client>& client,
- uint32_t *pSampleRate,
+ uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
audio_session_t sessionId,
- size_t *pNotificationFrameCount,
+ size_t *notificationFrames,
uid_t uid,
audio_input_flags_t *flags,
pid_t tid,
@@ -6721,30 +6721,16 @@
audio_port_handle_t portId)
{
size_t frameCount = *pFrameCount;
- size_t notificationFrameCount = *pNotificationFrameCount;
sp<RecordTrack> track;
status_t lStatus;
audio_input_flags_t inputFlags = mInput->flags;
- audio_input_flags_t requestedFlags = *flags;
- uint32_t sampleRate;
-
- lStatus = initCheck();
- if (lStatus != NO_ERROR) {
- ALOGE("createRecordTrack_l() audio driver not initialized");
- goto Exit;
- }
-
- if (*pSampleRate == 0) {
- *pSampleRate = mSampleRate;
- }
- sampleRate = *pSampleRate;
// special case for FAST flag considered OK if fast capture is present
if (hasFastCapture()) {
inputFlags = (audio_input_flags_t)(inputFlags | AUDIO_INPUT_FLAG_FAST);
}
- // Check if requested flags are compatible with input stream flags
+ // Check if requested flags are compatible with output stream flags
if ((*flags & inputFlags) != *flags) {
ALOGW("createRecordTrack_l(): mismatch between requested flags (%08x) and"
" input flags (%08x)",
@@ -6799,20 +6785,12 @@
}
}
- // If FAST or RAW flags were corrected, ask caller to request new input from audio policy
- if ((*flags & AUDIO_INPUT_FLAG_FAST) !=
- (requestedFlags & AUDIO_INPUT_FLAG_FAST)) {
- *flags = (audio_input_flags_t) (*flags & ~(AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW));
- lStatus = BAD_TYPE;
- goto Exit;
- }
-
// compute track buffer size in frames, and suggest the notification frame count
if (*flags & AUDIO_INPUT_FLAG_FAST) {
// fast track: frame count is exactly the pipe depth
frameCount = mPipeFramesP2;
// ignore requested notificationFrames, and always notify exactly once every HAL buffer
- notificationFrameCount = mFrameCount;
+ *notificationFrames = mFrameCount;
} else {
// not fast track: max notification period is resampled equivalent of one HAL buffer time
// or 20 ms if there is a fast capture
@@ -6831,12 +6809,17 @@
const size_t minFrameCount = maxNotificationFrames *
max(kMinNotifications, minNotificationsByMs);
frameCount = max(frameCount, minFrameCount);
- if (notificationFrameCount == 0 || notificationFrameCount > maxNotificationFrames) {
- notificationFrameCount = maxNotificationFrames;
+ if (*notificationFrames == 0 || *notificationFrames > maxNotificationFrames) {
+ *notificationFrames = maxNotificationFrames;
}
}
*pFrameCount = frameCount;
- *pNotificationFrameCount = notificationFrameCount;
+
+ lStatus = initCheck();
+ if (lStatus != NO_ERROR) {
+ ALOGE("createRecordTrack_l() audio driver not initialized");
+ goto Exit;
+ }
{ // scope for mLock
Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 17f26c5..c7b60d6 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1327,12 +1327,12 @@
sp<AudioFlinger::RecordThread::RecordTrack> createRecordTrack_l(
const sp<AudioFlinger::Client>& client,
- uint32_t *pSampleRate,
+ uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
audio_session_t sessionId,
- size_t *pNotificationFrameCount,
+ size_t *notificationFrames,
uid_t uid,
audio_input_flags_t *flags,
pid_t tid,
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index a3ea756..d4ce0b4 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -192,7 +192,7 @@
// where for AudioTrack (but not AudioRecord),
// 8-bit PCM samples are stored as 16-bit
const size_t mFrameCount;// size of track buffer given at createTrack() or
- // createRecord(), and then adjusted as needed
+ // openRecord(), and then adjusted as needed
const audio_session_t mSessionId;
uid_t mUid;
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index caa0703..9348ecd 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -26,6 +26,10 @@
LOCAL_32_BIT_ONLY := true
LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+LOCAL_CFLAGS += -DUSE_VNDBINDER
+endif
+
include $(BUILD_EXECUTABLE)
# service seccomp policy
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index 701ca6e..6f14a42 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -40,8 +40,10 @@
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
+#ifdef USE_VNDBINDER
android::ProcessState::initWithDriver("/dev/vndbinder");
android::ProcessState::self()->startThreadPool();
+#endif // USE_VNDBINDER
::android::hardware::configureRpcThreadpool(64, false);