audio policy: refactor audio record APIs

Refactor audio policy service APIs controlling audio record (startInput, stopInput, releaseInput)
To allow finer grain control per AudioRecord client and prepare for new concurrent capture
policy

Test: AudioRecord CTS test. manual test of capture use cases:
camcorder, OK Google VoIP

Change-Id: I4992fd5a115853c47be5dac5465989eb53f1287c
gugelfrei
Eric Laurent 7 years ago
parent c6116926de
commit 0f4b3c5449

@ -904,6 +904,7 @@ status_t AudioSystem::getInputForAttr(const audio_attributes_t *attr,
audio_session_t session,
pid_t pid,
uid_t uid,
const String16& opPackageName,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@ -912,35 +913,29 @@ status_t AudioSystem::getInputForAttr(const audio_attributes_t *attr,
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
return aps->getInputForAttr(
attr, input, session, pid, uid,
attr, input, session, pid, uid, opPackageName,
config, flags, selectedDeviceId, portId);
}
status_t AudioSystem::startInput(audio_io_handle_t input,
audio_session_t session,
audio_devices_t device,
uid_t uid,
bool *silenced)
status_t AudioSystem::startInput(audio_port_handle_t portId, bool *silenced)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->startInput(input, session, device, uid, silenced);
return aps->startInput(portId, silenced);
}
status_t AudioSystem::stopInput(audio_io_handle_t input,
audio_session_t session)
status_t AudioSystem::stopInput(audio_port_handle_t portId)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->stopInput(input, session);
return aps->stopInput(portId);
}
void AudioSystem::releaseInput(audio_io_handle_t input,
audio_session_t session)
void AudioSystem::releaseInput(audio_port_handle_t portId)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return;
aps->releaseInput(input, session);
aps->releaseInput(portId);
}
status_t AudioSystem::initStreamVolume(audio_stream_type_t stream,

@ -285,6 +285,7 @@ public:
audio_session_t session,
pid_t pid,
uid_t uid,
const String16& opPackageName,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@ -313,6 +314,7 @@ public:
data.writeInt32(session);
data.writeInt32(pid);
data.writeInt32(uid);
data.writeString16(opPackageName);
data.write(config, sizeof(audio_config_base_t));
data.writeInt32(flags);
data.writeInt32(*selectedDeviceId);
@ -331,18 +333,12 @@ public:
return NO_ERROR;
}
virtual status_t startInput(audio_io_handle_t input,
audio_session_t session,
audio_devices_t device,
uid_t uid,
virtual status_t startInput(audio_port_handle_t portId,
bool *silenced)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(input);
data.writeInt32(session);
data.writeInt32(device);
data.writeInt32(uid);
data.writeInt32(portId);
data.writeInt32(*silenced ? 1 : 0);
remote()->transact(START_INPUT, data, &reply);
status_t status = static_cast <status_t> (reply.readInt32());
@ -350,24 +346,20 @@ public:
return status;
}
virtual status_t stopInput(audio_io_handle_t input,
audio_session_t session)
virtual status_t stopInput(audio_port_handle_t portId)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(input);
data.writeInt32(session);
data.writeInt32(portId);
remote()->transact(STOP_INPUT, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
virtual void releaseInput(audio_io_handle_t input,
audio_session_t session)
virtual void releaseInput(audio_port_handle_t portId)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(input);
data.writeInt32(session);
data.writeInt32(portId);
remote()->transact(RELEASE_INPUT, data, &reply);
}
@ -1034,6 +1026,7 @@ status_t BnAudioPolicyService::onTransact(
audio_session_t session = (audio_session_t)data.readInt32();
pid_t pid = (pid_t)data.readInt32();
uid_t uid = (uid_t)data.readInt32();
const String16 opPackageName = data.readString16();
audio_config_base_t config;
memset(&config, 0, sizeof(audio_config_base_t));
data.read(&config, sizeof(audio_config_base_t));
@ -1041,7 +1034,7 @@ status_t BnAudioPolicyService::onTransact(
audio_port_handle_t selectedDeviceId = (audio_port_handle_t) data.readInt32();
audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
status_t status = getInputForAttr(&attr, &input, session, pid, uid,
&config,
opPackageName, &config,
flags, &selectedDeviceId, &portId);
reply->writeInt32(status);
if (status == NO_ERROR) {
@ -1054,12 +1047,9 @@ status_t BnAudioPolicyService::onTransact(
case START_INPUT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32());
audio_session_t session = static_cast <audio_session_t>(data.readInt32());
audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
uid_t uid = static_cast <uid_t>(data.readInt32());
audio_port_handle_t portId = static_cast <audio_port_handle_t>(data.readInt32());
bool silenced = data.readInt32() == 1;
status_t status = startInput(input, session, device, uid, &silenced);
status_t status = startInput(portId, &silenced);
reply->writeInt32(static_cast <uint32_t>(status));
reply->writeInt32(silenced ? 1 : 0);
return NO_ERROR;
@ -1067,17 +1057,15 @@ status_t BnAudioPolicyService::onTransact(
case STOP_INPUT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32());
audio_session_t session = static_cast <audio_session_t>(data.readInt32());
reply->writeInt32(static_cast <uint32_t>(stopInput(input, session)));
audio_port_handle_t portId = static_cast <audio_port_handle_t>(data.readInt32());
reply->writeInt32(static_cast <uint32_t>(stopInput(portId)));
return NO_ERROR;
} break;
case RELEASE_INPUT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32());
audio_session_t session = static_cast <audio_session_t>(data.readInt32());
releaseInput(input, session);
audio_port_handle_t portId = static_cast <audio_port_handle_t>(data.readInt32());
releaseInput(portId);
return NO_ERROR;
} break;

@ -239,20 +239,16 @@ public:
audio_session_t session,
pid_t pid,
uid_t uid,
const String16& opPackageName,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId);
static status_t startInput(audio_io_handle_t input,
audio_session_t session,
audio_devices_t device,
uid_t uid,
static status_t startInput(audio_port_handle_t portId,
bool *silenced);
static status_t stopInput(audio_io_handle_t input,
audio_session_t session);
static void releaseInput(audio_io_handle_t input,
audio_session_t session);
static status_t stopInput(audio_port_handle_t portId);
static void releaseInput(audio_port_handle_t portId);
static status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax);

@ -80,19 +80,15 @@ public:
audio_session_t session,
pid_t pid,
uid_t uid,
const String16& opPackageName,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId) = 0;
virtual status_t startInput(audio_io_handle_t input,
audio_session_t session,
audio_devices_t device,
uid_t uid,
virtual status_t startInput(audio_port_handle_t portId,
bool *silenced) = 0;
virtual status_t stopInput(audio_io_handle_t input,
audio_session_t session) = 0;
virtual void releaseInput(audio_io_handle_t input,
audio_session_t session) = 0;
virtual status_t stopInput(audio_port_handle_t portId) = 0;
virtual void releaseInput(audio_port_handle_t portId) = 0;
virtual status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax) = 0;

@ -321,6 +321,7 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
actualSessionId,
client.clientPid,
client.clientUid,
client.packageName,
config,
AUDIO_INPUT_FLAG_MMAP_NOIRQ, deviceId, &portId);
}
@ -340,7 +341,7 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
AudioSystem::releaseOutput(io, streamType, actualSessionId);
} else {
AudioSystem::releaseInput(io, actualSessionId);
AudioSystem::releaseInput(portId);
}
ret = NO_INIT;
}
@ -1663,7 +1664,7 @@ sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& inpu
// release previously opened input if retrying.
if (output.inputId != AUDIO_IO_HANDLE_NONE) {
recordTrack.clear();
AudioSystem::releaseInput(output.inputId, sessionId);
AudioSystem::releaseInput(portId);
output.inputId = AUDIO_IO_HANDLE_NONE;
}
lStatus = AudioSystem::getInputForAttr(&input.attr, &output.inputId,
@ -1671,6 +1672,7 @@ sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& inpu
// FIXME compare to AudioTrack
clientPid,
clientUid,
input.opPackageName,
&input.config,
output.flags, &output.selectedDeviceId, &portId);
@ -1739,7 +1741,7 @@ Exit:
}
recordTrack.clear();
if (output.inputId != AUDIO_IO_HANDLE_NONE) {
AudioSystem::releaseInput(output.inputId, sessionId);
AudioSystem::releaseInput(portId);
}
}

@ -6936,8 +6936,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac
if (recordTrack->isExternalTrack()) {
mLock.unlock();
bool silenced;
status = AudioSystem::startInput(mId, recordTrack->sessionId(),
mInDevice, recordTrack->uid(), &silenced);
status = AudioSystem::startInput(recordTrack->portId(), &silenced);
mLock.lock();
// FIXME should verify that recordTrack is still in mActiveTracks
if (status != NO_ERROR) {
@ -6969,7 +6968,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac
startError:
if (recordTrack->isExternalTrack()) {
AudioSystem::stopInput(mId, recordTrack->sessionId());
AudioSystem::stopInput(recordTrack->portId());
}
recordTrack->clearSyncStartEvent();
// FIXME I wonder why we do not reset the state here?
@ -7742,7 +7741,7 @@ void AudioFlinger::MmapThread::disconnect()
if (isOutput()) {
AudioSystem::releaseOutput(mId, streamType(), mSessionId);
} else {
AudioSystem::releaseInput(mId, mSessionId);
AudioSystem::releaseInput(mPortId);
}
}
@ -7837,6 +7836,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,
mSessionId,
client.clientPid,
client.clientUid,
client.packageName,
&config,
AUDIO_INPUT_FLAG_MMAP_NOIRQ,
&deviceId,
@ -7855,7 +7855,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,
} else {
// TODO: Block recording for idle UIDs (b/72134552)
bool silenced;
ret = AudioSystem::startInput(mId, mSessionId, mInDevice, client.clientUid, &silenced);
ret = AudioSystem::startInput(portId, &silenced);
}
// abort if start is rejected by audio policy manager
@ -7865,7 +7865,7 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,
if (isOutput()) {
AudioSystem::releaseOutput(mId, streamType(), mSessionId);
} else {
AudioSystem::releaseInput(mId, mSessionId);
AudioSystem::releaseInput(portId);
}
} else {
mHalStream->stop();
@ -7922,8 +7922,8 @@ status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
AudioSystem::stopOutput(mId, streamType(), track->sessionId());
AudioSystem::releaseOutput(mId, streamType(), track->sessionId());
} else {
AudioSystem::stopInput(mId, track->sessionId());
AudioSystem::releaseInput(mId, track->sessionId());
AudioSystem::stopInput(track->portId());
AudioSystem::releaseInput(track->portId());
}
sp<EffectChain> chain = getEffectChain_l(track->sessionId());

@ -1687,7 +1687,7 @@ void AudioFlinger::RecordThread::RecordTrack::stop()
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
if (recordThread->stop(this) && isExternalTrack()) {
AudioSystem::stopInput(mThreadIoHandle, mSessionId);
AudioSystem::stopInput(mPortId);
}
}
}
@ -1699,9 +1699,9 @@ void AudioFlinger::RecordThread::RecordTrack::destroy()
{
if (isExternalTrack()) {
if (mState == ACTIVE || mState == RESUMING) {
AudioSystem::stopInput(mThreadIoHandle, mSessionId);
AudioSystem::stopInput(mPortId);
}
AudioSystem::releaseInput(mThreadIoHandle, mSessionId);
AudioSystem::releaseInput(mPortId);
}
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {

@ -287,6 +287,7 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
audio_session_t session,
pid_t pid,
uid_t uid,
const String16& opPackageName,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
@ -367,6 +368,13 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
}
return status;
}
sp<AudioRecordClient> client =
new AudioRecordClient(*attr, *input, uid, pid, opPackageName, session);
client->active = false;
client->isConcurrent = false;
client->isVirtualDevice = false; //TODO : update from APM->getInputForAttr()
mAudioRecordClients.add(*portId, client);
}
if (audioPolicyEffects != 0) {
@ -379,23 +387,28 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
return NO_ERROR;
}
status_t AudioPolicyService::startInput(audio_io_handle_t input,
audio_session_t session,
audio_devices_t device,
uid_t uid,
bool *silenced)
status_t AudioPolicyService::startInput(audio_port_handle_t portId, bool *silenced)
{
// If UID inactive it records silence until becoming active
*silenced = !mUidPolicy->isUidActive(uid) && !is_virtual_input_device(device);
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
ssize_t index = mAudioRecordClients.indexOfKey(portId);
if (index < 0) {
return INVALID_OPERATION;
}
sp<AudioRecordClient> client = mAudioRecordClients.valueAt(index);
// If UID inactive it records silence until becoming active
*silenced = !mUidPolicy->isUidActive(client->uid) && !client->isVirtualDevice;
AudioPolicyInterface::concurrency_type__mask_t concurrency =
AudioPolicyInterface::API_INPUT_CONCURRENCY_NONE;
status_t status = mAudioPolicyManager->startInput(input, session, *silenced, &concurrency);
status_t status = mAudioPolicyManager->startInput(
client->input, client->session, *silenced, &concurrency);
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(concurrency & ~AudioPolicyInterface::API_INPUT_CONCURRENCY_ALL,
@ -413,38 +426,52 @@ status_t AudioPolicyService::startInput(audio_io_handle_t input,
return status;
}
status_t AudioPolicyService::stopInput(audio_io_handle_t input,
audio_session_t session)
status_t AudioPolicyService::stopInput(audio_port_handle_t portId)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
Mutex::Autolock _l(mLock);
return mAudioPolicyManager->stopInput(input, session);
ssize_t index = mAudioRecordClients.indexOfKey(portId);
if (index < 0) {
return INVALID_OPERATION;
}
sp<AudioRecordClient> client = mAudioRecordClients.valueAt(index);
return mAudioPolicyManager->stopInput(client->input, client->session);
}
void AudioPolicyService::releaseInput(audio_io_handle_t input,
audio_session_t session)
void AudioPolicyService::releaseInput(audio_port_handle_t portId)
{
if (mAudioPolicyManager == NULL) {
return;
}
sp<AudioPolicyEffects>audioPolicyEffects;
sp<AudioRecordClient> client;
{
Mutex::Autolock _l(mLock);
audioPolicyEffects = mAudioPolicyEffects;
ssize_t index = mAudioRecordClients.indexOfKey(portId);
if (index < 0) {
return;
}
client = mAudioRecordClients.valueAt(index);
mAudioRecordClients.removeItem(portId);
}
if (client == 0) {
return;
}
if (audioPolicyEffects != 0) {
// release audio processors from the input
status_t status = audioPolicyEffects->releaseInputEffects(input, session);
status_t status = audioPolicyEffects->releaseInputEffects(client->input, client->session);
if(status != NO_ERROR) {
ALOGW("Failed to release effects on input %d", input);
ALOGW("Failed to release effects on input %d", client->input);
}
}
{
Mutex::Autolock _l(mLock);
mAudioPolicyManager->releaseInput(input, session);
mAudioPolicyManager->releaseInput(client->input, client->session);
}
}

@ -98,19 +98,15 @@ public:
audio_session_t session,
pid_t pid,
uid_t uid,
const String16& opPackageName,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId = NULL,
audio_port_handle_t *portId = NULL);
virtual status_t startInput(audio_io_handle_t input,
audio_session_t session,
audio_devices_t device,
uid_t uid,
virtual status_t startInput(audio_port_handle_t portId,
bool *silenced);
virtual status_t stopInput(audio_io_handle_t input,
audio_session_t session);
virtual void releaseInput(audio_io_handle_t input,
audio_session_t session);
virtual status_t stopInput(audio_port_handle_t portId);
virtual void releaseInput(audio_port_handle_t portId);
virtual status_t initStreamVolume(audio_stream_type_t stream,
int indexMin,
int indexMax);
@ -611,6 +607,31 @@ private:
bool mAudioPortCallbacksEnabled;
};
// --- AudioRecordClient ---
// Information about each registered AudioRecord client
// (between calls to getInputForAttr() and releaseInput())
class AudioRecordClient : public RefBase {
public:
AudioRecordClient(const audio_attributes_t attributes,
const audio_io_handle_t input, uid_t uid, pid_t pid,
const String16& opPackageName, const audio_session_t session) :
attributes(attributes),
input(input), uid(uid), pid(pid),
opPackageName(opPackageName), session(session),
active(false), isConcurrent(false), isVirtualDevice(false) {}
virtual ~AudioRecordClient() {}
const audio_attributes_t attributes; // source, flags ...
const audio_io_handle_t input; // audio HAL input IO handle
const uid_t uid; // client UID
const pid_t pid; // client PID
const String16 opPackageName; // client package name
const audio_session_t session; // audio session ID
bool active; // Capture is active or inactive
bool isConcurrent; // is allowed to concurrent capture
bool isVirtualDevice; // uses vitual device: updated by APM::getInputForAttr()
};
// Internal dump utilities.
status_t dumpPermissionDenial(int fd);
@ -636,6 +657,7 @@ private:
audio_mode_t mPhoneState;
sp<UidPolicy> mUidPolicy;
DefaultKeyedVector< audio_port_handle_t, sp<AudioRecordClient> > mAudioRecordClients;
};
} // namespace android

Loading…
Cancel
Save