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
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index f1d7d86..0ce562c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -287,6 +287,7 @@
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 @@
}
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 @@
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 @@
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);
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c21aa58..bfa3ef4 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -98,19 +98,15 @@
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 @@
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 @@
audio_mode_t mPhoneState;
sp<UidPolicy> mUidPolicy;
+ DefaultKeyedVector< audio_port_handle_t, sp<AudioRecordClient> > mAudioRecordClients;
};
} // namespace android