summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-05-20 11:27:36 -0700
committerEric Laurent <elaurent@google.com>2014-05-29 18:01:58 -0700
commitb52c152d553556b2d227ffc943489de0c60b4b02 (patch)
treebcaca952efbd1ffa7eefa7251beafc3d2574a04a /services/audiopolicy
parent6a94d69dc4f32abb53c466a96f905bb199be6417 (diff)
downloadframeworks_av-b52c152d553556b2d227ffc943489de0c60b4b02.zip
frameworks_av-b52c152d553556b2d227ffc943489de0c60b4b02.tar.gz
frameworks_av-b52c152d553556b2d227ffc943489de0c60b4b02.tar.bz2
audio policy: add routing update client interface
Added IAudioPolicyServiceClient client binder interface for client process to receive notifications from AudioPolicyService when audio ports are added/removed or audio patches created/released. The audio patches owned by a given client are automatically released when this client binder dies. Bug: 14815883. Change-Id: I6013f6aec03b50565cffb1ad2cd1f0f8852032c5
Diffstat (limited to 'services/audiopolicy')
-rw-r--r--services/audiopolicy/AudioPolicyClientImpl.cpp10
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h3
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp12
-rw-r--r--services/audiopolicy/AudioPolicyService.cpp133
-rw-r--r--services/audiopolicy/AudioPolicyService.h39
5 files changed, 196 insertions, 1 deletions
diff --git a/services/audiopolicy/AudioPolicyClientImpl.cpp b/services/audiopolicy/AudioPolicyClientImpl.cpp
index 8225e36..cbab841 100644
--- a/services/audiopolicy/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/AudioPolicyClientImpl.cpp
@@ -195,4 +195,14 @@ status_t AudioPolicyService::AudioPolicyClient::releaseAudioPatch(audio_patch_ha
return mAudioPolicyService->clientReleaseAudioPatch(handle, delayMs);
}
+void AudioPolicyService::AudioPolicyClient::onAudioPortListUpdate()
+{
+ mAudioPolicyService->onAudioPortListUpdate();
+}
+
+void AudioPolicyService::AudioPolicyClient::onAudioPatchListUpdate()
+{
+ mAudioPolicyService->onAudioPatchListUpdate();
+}
+
}; // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 98ad1d4..e0c7f61 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -273,6 +273,9 @@ public:
virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
int delayMs) = 0;
+ virtual void onAudioPortListUpdate() = 0;
+
+ virtual void onAudioPatchListUpdate() = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 905418b..b5b26d3 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -286,6 +286,7 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
} else {
+ mpClientInterface->onAudioPortListUpdate();
return NO_ERROR;
}
} // end if is output device
@@ -343,6 +344,7 @@ status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
closeAllInputs();
+ mpClientInterface->onAudioPortListUpdate();
return NO_ERROR;
} // end if is input device
@@ -754,6 +756,7 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream,
}
mPreviousOutputs = mOutputs;
ALOGV("getOutput() returns new direct output %d", output);
+ mpClientInterface->onAudioPortListUpdate();
return output;
}
@@ -986,6 +989,7 @@ void AudioPolicyManager::releaseOutput(audio_io_handle_t output)
if (dstOutput != mPrimaryOutput) {
mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput);
}
+ mpClientInterface->onAudioPortListUpdate();
}
}
}
@@ -1067,6 +1071,7 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
return 0;
}
addInput(input, inputDesc);
+ mpClientInterface->onAudioPortListUpdate();
return input;
}
@@ -1152,6 +1157,7 @@ void AudioPolicyManager::releaseInput(audio_io_handle_t input)
delete mInputs.valueAt(index);
mInputs.removeItem(input);
nextAudioPortGeneration();
+ mpClientInterface->onAudioPortListUpdate();
ALOGV("releaseInput() exit");
}
@@ -1904,6 +1910,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
patchDesc->mAfPatchHandle = afPatchHandle;
*handle = patchDesc->mHandle;
nextAudioPortGeneration();
+ mpClientInterface->onAudioPatchListUpdate();
} else {
ALOGW("createAudioPatch() patch panel could not connect device patch, error %d",
status);
@@ -1967,6 +1974,7 @@ status_t AudioPolicyManager::releaseAudioPatch(audio_patch_handle_t handle,
status, patchDesc->mAfPatchHandle);
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
+ mpClientInterface->onAudioPatchListUpdate();
} else {
return BAD_VALUE;
}
@@ -3584,6 +3592,7 @@ uint32_t AudioPolicyManager::setOutputDevice(audio_io_handle_t output,
}
outputDesc->mPatchHandle = patchDesc->mHandle;
nextAudioPortGeneration();
+ mpClientInterface->onAudioPatchListUpdate();
}
}
}
@@ -3614,6 +3623,7 @@ status_t AudioPolicyManager::resetOutputDevice(audio_io_handle_t output,
outputDesc->mPatchHandle = 0;
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
+ mpClientInterface->onAudioPatchListUpdate();
return status;
}
@@ -3669,6 +3679,7 @@ status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input,
}
inputDesc->mPatchHandle = patchDesc->mHandle;
nextAudioPortGeneration();
+ mpClientInterface->onAudioPatchListUpdate();
}
}
}
@@ -3694,6 +3705,7 @@ status_t AudioPolicyManager::resetInputDevice(audio_io_handle_t input,
inputDesc->mPatchHandle = 0;
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
+ mpClientInterface->onAudioPatchListUpdate();
return status;
}
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index ea573a4..f3d92ed 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -148,6 +148,61 @@ AudioPolicyService::~AudioPolicyService()
delete mAudioPolicyManager;
delete mAudioPolicyClient;
#endif
+
+ mNotificationClients.clear();
+}
+
+// A notification client is always registered by AudioSystem when the client process
+// connects to AudioPolicyService.
+void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
+{
+
+ Mutex::Autolock _l(mLock);
+
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ if (mNotificationClients.indexOfKey(uid) < 0) {
+ sp<NotificationClient> notificationClient = new NotificationClient(this,
+ client,
+ uid);
+ ALOGV("registerClient() client %p, uid %d", client.get(), uid);
+
+ mNotificationClients.add(uid, notificationClient);
+
+ sp<IBinder> binder = client->asBinder();
+ binder->linkToDeath(notificationClient);
+ }
+}
+
+// removeNotificationClient() is called when the client process dies.
+void AudioPolicyService::removeNotificationClient(uid_t uid)
+{
+ Mutex::Autolock _l(mLock);
+
+ mNotificationClients.removeItem(uid);
+
+#ifndef USE_LEGACY_AUDIO_POLICY
+ if (mAudioPolicyManager) {
+ mAudioPolicyManager->clearAudioPatches(uid);
+ }
+#endif
+}
+
+void AudioPolicyService::onAudioPortListUpdate()
+{
+ mOutputCommandThread->updateAudioPortListCommand();
+}
+
+void AudioPolicyService::doOnAudioPortListUpdate()
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onAudioPortListUpdate();
+ }
+}
+
+void AudioPolicyService::onAudioPatchListUpdate()
+{
+ mOutputCommandThread->updateAudioPatchListCommand();
}
status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
@@ -163,6 +218,47 @@ status_t AudioPolicyService::clientReleaseAudioPatch(audio_patch_handle_t handle
return mAudioCommandThread->releaseAudioPatchCommand(handle, delayMs);
}
+void AudioPolicyService::doOnAudioPatchListUpdate()
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onAudioPatchListUpdate();
+ }
+}
+
+AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
+ const sp<IAudioPolicyServiceClient>& client,
+ uid_t uid)
+ : mService(service), mUid(uid), mAudioPolicyServiceClient(client)
+{
+}
+
+AudioPolicyService::NotificationClient::~NotificationClient()
+{
+}
+
+void AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who __unused)
+{
+ sp<NotificationClient> keep(this);
+ sp<AudioPolicyService> service = mService.promote();
+ if (service != 0) {
+ service->removeNotificationClient(mUid);
+ }
+}
+
+void AudioPolicyService::NotificationClient::onAudioPortListUpdate()
+{
+ if (mAudioPolicyServiceClient != 0) {
+ mAudioPolicyServiceClient->onAudioPortListUpdate();
+ }
+}
+
+void AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
+{
+ if (mAudioPolicyServiceClient != 0) {
+ mAudioPolicyServiceClient->onAudioPatchListUpdate();
+ }
+}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
@@ -390,6 +486,26 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
command->mStatus = af->releaseAudioPatch(data->mHandle);
}
} break;
+ case UPDATE_AUDIOPORT_LIST: {
+ ALOGV("AudioCommandThread() processing update audio port list");
+ sp<AudioPolicyService> svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnAudioPortListUpdate();
+ mLock.lock();
+ }break;
+ case UPDATE_AUDIOPATCH_LIST: {
+ ALOGV("AudioCommandThread() processing update audio patch list");
+ sp<AudioPolicyService> svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnAudioPatchListUpdate();
+ mLock.lock();
+ }break;
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -584,6 +700,22 @@ status_t AudioPolicyService::AudioCommandThread::releaseAudioPatchCommand(audio_
return sendCommand(command, delayMs);
}
+void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand()
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = UPDATE_AUDIOPORT_LIST;
+ ALOGV("AudioCommandThread() adding update audio port list");
+ sendCommand(command);
+}
+
+void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand()
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = UPDATE_AUDIOPATCH_LIST;
+ ALOGV("AudioCommandThread() adding update audio patch list");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@@ -602,7 +734,6 @@ status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& c
return command->mStatus;
}
-
// insertCommand_l() must be called with mLock held
void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs)
{
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 9f88b1e..a579d1d 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -154,6 +154,8 @@ public:
unsigned int *generation);
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+ virtual void registerClient(const sp<IAudioPolicyServiceClient>& client);
+
status_t doStopOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session = 0);
@@ -164,6 +166,11 @@ public:
int delayMs);
status_t clientReleaseAudioPatch(audio_patch_handle_t handle,
int delayMs);
+ void removeNotificationClient(uid_t uid);
+ void onAudioPortListUpdate();
+ void doOnAudioPortListUpdate();
+ void onAudioPatchListUpdate();
+ void doOnAudioPatchListUpdate();
private:
AudioPolicyService() ANDROID_API;
@@ -192,6 +199,8 @@ private:
RELEASE_OUTPUT,
CREATE_AUDIO_PATCH,
RELEASE_AUDIO_PATCH,
+ UPDATE_AUDIOPORT_LIST,
+ UPDATE_AUDIOPATCH_LIST
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -223,6 +232,8 @@ private:
int delayMs);
status_t releaseAudioPatchCommand(audio_patch_handle_t handle,
int delayMs);
+ void updateAudioPortListCommand();
+ void updateAudioPatchListCommand();
void insertCommand_l(AudioCommand *command, int delayMs = 0);
@@ -454,10 +465,36 @@ private:
virtual status_t releaseAudioPatch(audio_patch_handle_t handle,
int delayMs);
+ virtual void onAudioPortListUpdate();
+ virtual void onAudioPatchListUpdate();
+
private:
AudioPolicyService *mAudioPolicyService;
};
+ // --- Notification Client ---
+ class NotificationClient : public IBinder::DeathRecipient {
+ public:
+ NotificationClient(const sp<AudioPolicyService>& service,
+ const sp<IAudioPolicyServiceClient>& client,
+ uid_t uid);
+ virtual ~NotificationClient();
+
+ void onAudioPortListUpdate();
+ void onAudioPatchListUpdate();
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ NotificationClient(const NotificationClient&);
+ NotificationClient& operator = (const NotificationClient&);
+
+ const wp<AudioPolicyService> mService;
+ const uid_t mUid;
+ const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
+ };
+
static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
void setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled);
@@ -494,6 +531,8 @@ private:
KeyedVector< audio_source_t, InputSourceDesc* > mInputSources;
KeyedVector< audio_io_handle_t, InputDesc* > mInputs;
+
+ DefaultKeyedVector< uid_t, sp<NotificationClient> > mNotificationClients;
};
}; // namespace android