From 0f4b3c5449f85c1cd78e1b9ac4850de962b8edbe Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 5 Jan 2018 11:46:13 +0100 Subject: [PATCH] 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 --- media/libaudioclient/AudioSystem.cpp | 21 +++---- media/libaudioclient/IAudioPolicyService.cpp | 44 +++++-------- .../include/media/AudioSystem.h | 12 ++-- .../include/media/IAudioPolicyService.h | 12 ++-- services/audioflinger/AudioFlinger.cpp | 8 ++- services/audioflinger/Threads.cpp | 16 ++--- services/audioflinger/Tracks.cpp | 6 +- .../service/AudioPolicyInterfaceImpl.cpp | 61 +++++++++++++------ .../audiopolicy/service/AudioPolicyService.h | 38 +++++++++--- 9 files changed, 122 insertions(+), 96 deletions(-) diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp index 3bb09d2d9d..7783ad364a 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -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& 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& 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& 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& 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, diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index 6478975598..b91e4cf191 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -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 (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 (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 (data.readInt32()); - audio_session_t session = static_cast (data.readInt32()); - audio_devices_t device = static_cast (data.readInt32()); - uid_t uid = static_cast (data.readInt32()); + audio_port_handle_t portId = static_cast (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 (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 (data.readInt32()); - audio_session_t session = static_cast (data.readInt32()); - reply->writeInt32(static_cast (stopInput(input, session))); + audio_port_handle_t portId = static_cast (data.readInt32()); + reply->writeInt32(static_cast (stopInput(portId))); return NO_ERROR; } break; case RELEASE_INPUT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); - audio_io_handle_t input = static_cast (data.readInt32()); - audio_session_t session = static_cast (data.readInt32()); - releaseInput(input, session); + audio_port_handle_t portId = static_cast (data.readInt32()); + releaseInput(portId); return NO_ERROR; } break; diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h index f7c3d039be..52dcfaad88 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -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); diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index 533892731b..949d593dcd 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -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; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index e362530e7b..baab926049 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -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 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 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); } } diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 420e6e1f08..3d270fca02 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -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 chain = getEffectChain_l(track->sessionId()); diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index cdd8ca00ef..06bbf1e395 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -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 thread = mThread.promote(); if (thread != 0) { diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index f1d7d86850..0ce562c43d 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -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 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 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 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; } spaudioPolicyEffects; + sp 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); } } diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index c21aa58e04..bfa3ef40d5 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -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 mUidPolicy; + DefaultKeyedVector< audio_port_handle_t, sp > mAudioRecordClients; }; } // namespace android