summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--include/media/AudioSystem.h25
-rw-r--r--include/media/IAudioPolicyService.h2
-rw-r--r--include/media/IAudioPolicyServiceClient.h56
-rw-r--r--media/libmedia/Android.mk1
-rw-r--r--media/libmedia/AudioSystem.cpp30
-rw-r--r--media/libmedia/IAudioPolicyService.cpp17
-rw-r--r--media/libmedia/IAudioPolicyServiceClient.cpp83
-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
12 files changed, 407 insertions, 4 deletions
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index a79a9ff..6fe0c7f 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -19,6 +19,7 @@
#include <hardware/audio_effect.h>
#include <media/IAudioFlingerClient.h>
+#include <media/IAudioPolicyServiceClient.h>
#include <system/audio.h>
#include <system/audio_policy.h>
#include <utils/Errors.h>
@@ -301,6 +302,21 @@ public:
// ----------------------------------------------------------------------------
+ class AudioPortCallback : public RefBase
+ {
+ public:
+
+ AudioPortCallback() {}
+ virtual ~AudioPortCallback() {}
+
+ virtual void onAudioPortListUpdate() = 0;
+ virtual void onAudioPatchListUpdate() = 0;
+ virtual void onServiceDied() = 0;
+
+ };
+
+ static void setAudioPortCallback(sp<AudioPortCallback> callBack);
+
private:
class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
@@ -319,7 +335,8 @@ private:
virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
};
- class AudioPolicyServiceClient: public IBinder::DeathRecipient
+ class AudioPolicyServiceClient: public IBinder::DeathRecipient,
+ public BnAudioPolicyServiceClient
{
public:
AudioPolicyServiceClient() {
@@ -327,6 +344,10 @@ private:
// DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
+
+ // IAudioPolicyServiceClient
+ virtual void onAudioPortListUpdate();
+ virtual void onAudioPatchListUpdate();
};
static sp<AudioFlingerClient> gAudioFlingerClient;
@@ -349,6 +370,8 @@ private:
// list of output descriptors containing cached parameters
// (sampling rate, framecount, channel count...)
static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
+
+ static sp<AudioPortCallback> gAudioPortCallback;
};
}; // namespace android
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 6b6df6e..d422aa3 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -25,6 +25,7 @@
#include <utils/Errors.h>
#include <binder/IInterface.h>
#include <media/AudioSystem.h>
+#include <media/IAudioPolicyServiceClient.h>
#include <system/audio_policy.h>
@@ -124,6 +125,7 @@ public:
/* Set audio port configuration */
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
+ virtual void registerClient(const sp<IAudioPolicyServiceClient>& client) = 0;
};
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
new file mode 100644
index 0000000..59df046
--- /dev/null
+++ b/include/media/IAudioPolicyServiceClient.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IAUDIOPOLICYSERVICECLIENT_H
+#define ANDROID_IAUDIOPOLICYSERVICECLIENT_H
+
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <system/audio.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioPolicyServiceClient : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioPolicyServiceClient);
+
+ // Notifies a change of audio port configuration.
+ virtual void onAudioPortListUpdate() = 0;
+ // Notifies a change of audio patch configuration.
+ virtual void onAudioPatchListUpdate() = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioPolicyServiceClient : public BnInterface<IAudioPolicyServiceClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOPOLICYSERVICECLIENT_H
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index f3770e4..69eead3 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -44,6 +44,7 @@ LOCAL_SRC_FILES:= \
JetPlayer.cpp \
IOMX.cpp \
IAudioPolicyService.cpp \
+ IAudioPolicyServiceClient.cpp \
MediaScanner.cpp \
MediaScannerClient.cpp \
CharacterEncodingDetector.cpp \
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 845ee20..eafb3ad 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -45,6 +45,7 @@ audio_format_t AudioSystem::gPrevInFormat;
audio_channel_mask_t AudioSystem::gPrevInChannelMask;
size_t AudioSystem::gInBuffSize = 0; // zero indicates cache is invalid
+sp<AudioSystem::AudioPortCallback> AudioSystem::gAudioPortCallback;
// establish binder interface to AudioFlinger service
const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
@@ -528,6 +529,7 @@ void AudioSystem::setErrorCallback(audio_error_callback cb)
gAudioErrorCallback = cb;
}
+
bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType)
{
switch (streamType) {
@@ -566,6 +568,7 @@ const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
}
binder->linkToDeath(gAudioPolicyServiceClient);
gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
+ gAudioPolicyService->registerClient(gAudioPolicyServiceClient);
gLock.unlock();
} else {
gLock.unlock();
@@ -880,14 +883,39 @@ status_t AudioSystem::setAudioPortConfig(const struct audio_port_config *config)
return aps->setAudioPortConfig(config);
}
+void AudioSystem::setAudioPortCallback(sp<AudioPortCallback> callBack)
+{
+ Mutex::Autolock _l(gLock);
+ gAudioPortCallback = callBack;
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
{
- Mutex::Autolock _l(AudioSystem::gLock);
+ Mutex::Autolock _l(gLock);
+ if (gAudioPortCallback != 0) {
+ gAudioPortCallback->onServiceDied();
+ }
AudioSystem::gAudioPolicyService.clear();
ALOGW("AudioPolicyService server died!");
}
+void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate()
+{
+ Mutex::Autolock _l(gLock);
+ if (gAudioPortCallback != 0) {
+ gAudioPortCallback->onAudioPortListUpdate();
+ }
+}
+
+void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate()
+{
+ Mutex::Autolock _l(gLock);
+ if (gAudioPortCallback != 0) {
+ gAudioPortCallback->onAudioPatchListUpdate();
+ }
+}
+
}; // namespace android
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index ad2d4eb..eee72c5 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -63,7 +63,8 @@ enum {
CREATE_AUDIO_PATCH,
RELEASE_AUDIO_PATCH,
LIST_AUDIO_PATCHES,
- SET_AUDIO_PORT_CONFIG
+ SET_AUDIO_PORT_CONFIG,
+ REGISTER_CLIENT
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -524,6 +525,13 @@ public:
}
return status;
}
+ virtual void registerClient(const sp<IAudioPolicyServiceClient>& client)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeStrongBinder(client->asBinder());
+ remote()->transact(REGISTER_CLIENT, data, &reply);
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -910,6 +918,13 @@ status_t BnAudioPolicyService::onTransact(
reply->writeInt32(status);
return NO_ERROR;
}
+ case REGISTER_CLIENT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
+ data.readStrongBinder());
+ registerClient(client);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp
new file mode 100644
index 0000000..e802277
--- /dev/null
+++ b/media/libmedia/IAudioPolicyServiceClient.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IAudioPolicyServiceClient"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioPolicyServiceClient.h>
+#include <media/AudioSystem.h>
+
+namespace android {
+
+enum {
+ PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION,
+ PATCH_LIST_UPDATE
+};
+
+class BpAudioPolicyServiceClient : public BpInterface<IAudioPolicyServiceClient>
+{
+public:
+ BpAudioPolicyServiceClient(const sp<IBinder>& impl)
+ : BpInterface<IAudioPolicyServiceClient>(impl)
+ {
+ }
+
+ void onAudioPortListUpdate()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
+ remote()->transact(PORT_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ void onAudioPatchListUpdate()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
+ remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnAudioPolicyServiceClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case PORT_LIST_UPDATE: {
+ CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
+ onAudioPortListUpdate();
+ return NO_ERROR;
+ } break;
+ case PATCH_LIST_UPDATE: {
+ CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply);
+ onAudioPatchListUpdate();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
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