From de80105c3f2db0eabd47640c49387ea3b44d4782 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 14 Apr 2015 19:10:14 -0700 Subject: AudioPolicyManager: notification of dynamic policy mix activity Implement non-stream type specific ref counting in output descriptors to keep track of mix activity. Notify audio policy client of mix activity changes. Bug 20226914 Change-Id: Iec939cb640c58056f88947b611d23b4bb6d8a11b --- include/media/AudioPolicy.h | 11 ++++- include/media/AudioSystem.h | 1 + include/media/IAudioPolicyServiceClient.h | 2 + media/libmedia/AudioPolicy.cpp | 2 + media/libmedia/AudioSystem.cpp | 6 +++ media/libmedia/IAudioPolicyServiceClient.cpp | 19 +++++++- services/audiopolicy/AudioPolicyInterface.h | 2 + .../include/AudioOutputDescriptor.h | 1 + .../src/AudioOutputDescriptor.cpp | 23 ++++++++- .../audiopolicy/service/AudioPolicyClientImpl.cpp | 6 +++ .../audiopolicy/service/AudioPolicyService.cpp | 55 ++++++++++++++++++++++ services/audiopolicy/service/AudioPolicyService.h | 17 ++++++- 12 files changed, 139 insertions(+), 6 deletions(-) diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h index a755e1e..800b27b 100644 --- a/include/media/AudioPolicy.h +++ b/include/media/AudioPolicy.h @@ -38,9 +38,15 @@ namespace android { #define MIX_TYPE_PLAYERS 0 #define MIX_TYPE_RECORDERS 1 +#define MIX_STATE_DISABLED -1 +#define MIX_STATE_IDLE 0 +#define MIX_STATE_MIXING 1 + #define ROUTE_FLAG_RENDER 0x1 #define ROUTE_FLAG_LOOP_BACK (0x1 << 1) +#define MIX_FLAG_NOTIFY_ACTIVITY 0x1 + #define MAX_MIXES_PER_POLICY 10 #define MAX_CRITERIA_PER_MIX 20 @@ -63,9 +69,9 @@ class AudioMix { public: AudioMix() {} AudioMix(Vector criteria, uint32_t mixType, audio_config_t format, - uint32_t routeFlags, String8 registrationId) : + uint32_t routeFlags, String8 registrationId, uint32_t flags) : mCriteria(criteria), mMixType(mixType), mFormat(format), - mRouteFlags(routeFlags), mRegistrationId(registrationId) {} + mRouteFlags(routeFlags), mRegistrationId(registrationId), mFlags(flags){} status_t readFromParcel(Parcel *parcel); status_t writeToParcel(Parcel *parcel) const; @@ -75,6 +81,7 @@ public: audio_config_t mFormat; uint32_t mRouteFlags; String8 mRegistrationId; + uint32_t mFlags; }; }; // namespace android diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 3b6db8c..927283c 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -384,6 +384,7 @@ private: // IAudioPolicyServiceClient virtual void onAudioPortListUpdate(); virtual void onAudioPatchListUpdate(); + virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); private: Mutex mLock; diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h index 59df046..a7f2cc3 100644 --- a/include/media/IAudioPolicyServiceClient.h +++ b/include/media/IAudioPolicyServiceClient.h @@ -35,6 +35,8 @@ public: virtual void onAudioPortListUpdate() = 0; // Notifies a change of audio patch configuration. virtual void onAudioPatchListUpdate() = 0; + // Notifies a change in the mixing state of a specific mix in a dynamic audio policy + virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0; }; diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp index c7dafcb..786eb63 100644 --- a/media/libmedia/AudioPolicy.cpp +++ b/media/libmedia/AudioPolicy.cpp @@ -68,6 +68,7 @@ status_t AudioMix::readFromParcel(Parcel *parcel) mFormat.format = (audio_format_t)parcel->readInt32(); mRouteFlags = parcel->readInt32(); mRegistrationId = parcel->readString8(); + mFlags = (uint32_t)parcel->readInt32(); size_t size = (size_t)parcel->readInt32(); if (size > MAX_CRITERIA_PER_MIX) { size = MAX_CRITERIA_PER_MIX; @@ -89,6 +90,7 @@ status_t AudioMix::writeToParcel(Parcel *parcel) const parcel->writeInt32(mFormat.format); parcel->writeInt32(mRouteFlags); parcel->writeString8(mRegistrationId); + parcel->writeInt32(mFlags); size_t size = mCriteria.size(); if (size > MAX_CRITERIA_PER_MIX) { size = MAX_CRITERIA_PER_MIX; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 8db72ee..d1aeba1 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -1033,6 +1033,12 @@ void AudioSystem::AudioPolicyServiceClient::onAudioPatchListUpdate() } } +void AudioSystem::AudioPolicyServiceClient::onDynamicPolicyMixStateUpdate( + String8 regId, int32_t state) +{ + ALOGV("TODO propagate onDynamicPolicyMixStateUpdate(%s, %d)", regId.string(), state); +} + void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) { { diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp index 7c65878..65cc7d6 100644 --- a/media/libmedia/IAudioPolicyServiceClient.cpp +++ b/media/libmedia/IAudioPolicyServiceClient.cpp @@ -29,7 +29,8 @@ namespace android { enum { PORT_LIST_UPDATE = IBinder::FIRST_CALL_TRANSACTION, - PATCH_LIST_UPDATE + PATCH_LIST_UPDATE, + MIX_STATE_UPDATE }; class BpAudioPolicyServiceClient : public BpInterface @@ -53,6 +54,15 @@ public: data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); remote()->transact(PATCH_LIST_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); } + + void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor()); + data.writeString8(regId); + data.writeInt32(state); + remote()->transact(MIX_STATE_UPDATE, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(AudioPolicyServiceClient, "android.media.IAudioPolicyServiceClient"); @@ -73,6 +83,13 @@ status_t BnAudioPolicyServiceClient::onTransact( onAudioPatchListUpdate(); return NO_ERROR; } break; + case MIX_STATE_UPDATE: { + CHECK_INTERFACE(IAudioPolicyServiceClient, data, reply); + String8 regId = data.readString8(); + int32_t state = data.readInt32(); + onDynamicPolicyMixStateUpdate(regId, state); + return NO_ERROR; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 48d0e29..4fa472e 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -320,6 +320,8 @@ public: virtual void onAudioPatchListUpdate() = 0; virtual audio_unique_id_t newAudioUniqueId() = 0; + + virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0; }; extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface); diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index f1aee46..50f622d 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -123,6 +123,7 @@ public: sp mOutput1; // used by duplicated outputs: first output sp mOutput2; // used by duplicated outputs: second output uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only) + uint32_t mGlobalRefCount; // non-stream-specific ref count }; class SwAudioOutputCollection : diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index 596aa1d..144d8ad 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -225,7 +225,7 @@ SwAudioOutputDescriptor::SwAudioOutputDescriptor( : AudioOutputDescriptor(profile, clientInterface), mProfile(profile), mIoHandle(0), mLatency(0), mFlags((audio_output_flags_t)0), mPolicyMix(NULL), - mOutput1(0), mOutput2(0), mDirectOpenCount(0) + mOutput1(0), mOutput2(0), mDirectOpenCount(0), mGlobalRefCount(0) { if (profile != NULL) { mFlags = (audio_output_flags_t)profile->mFlags; @@ -305,6 +305,27 @@ void SwAudioOutputDescriptor::changeRefCount(audio_stream_type_t stream, mOutput2->changeRefCount(stream, delta); } AudioOutputDescriptor::changeRefCount(stream, delta); + + // handle stream-independent ref count + uint32_t oldGlobalRefCount = mGlobalRefCount; + if ((delta + (int)mGlobalRefCount) < 0) { + ALOGW("changeRefCount() invalid delta %d globalRefCount %d", delta, mGlobalRefCount); + mGlobalRefCount = 0; + } else { + mGlobalRefCount += delta; + } + if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) { + if ((mPolicyMix != NULL) && ((mPolicyMix->mFlags & MIX_FLAG_NOTIFY_ACTIVITY) != 0)) { + mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId, + MIX_STATE_MIXING); + } + + } else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) { + if ((mPolicyMix != NULL) && ((mPolicyMix->mFlags & MIX_FLAG_NOTIFY_ACTIVITY) != 0)) { + mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId, + MIX_STATE_IDLE); + } + } } diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp index 3e090e9..489a9be 100644 --- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp @@ -213,6 +213,12 @@ void AudioPolicyService::AudioPolicyClient::onAudioPatchListUpdate() mAudioPolicyService->onAudioPatchListUpdate(); } +void AudioPolicyService::AudioPolicyClient::onDynamicPolicyMixStateUpdate( + String8 regId, int32_t state) +{ + mAudioPolicyService->onDynamicPolicyMixStateUpdate(regId, state); +} + audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId() { return AudioSystem::newAudioUniqueId(); diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index 00f188f..ccf9f9b 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -222,6 +222,21 @@ void AudioPolicyService::doOnAudioPatchListUpdate() } } +void AudioPolicyService::onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) +{ + ALOGV("AudioPolicyService::onDynamicPolicyMixStateUpdate(%s, %d)", + regId.string(), state); + mOutputCommandThread->dynamicPolicyMixStateUpdateCommand(regId, state); +} + +void AudioPolicyService::doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state) +{ + Mutex::Autolock _l(mNotificationClientsLock); + for (size_t i = 0; i < mNotificationClients.size(); i++) { + mNotificationClients.valueAt(i)->onDynamicPolicyMixStateUpdate(regId, state); + } +} + status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config, int delayMs) { @@ -262,6 +277,14 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() } } +void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate( + String8 regId, int32_t state) +{ + if (mAudioPolicyServiceClient != 0) { + mAudioPolicyServiceClient->onDynamicPolicyMixStateUpdate(regId, state); + } +} + void AudioPolicyService::binderDied(const wp& who) { ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), IPCThreadState::self()->getCallingPid()); @@ -511,6 +534,20 @@ bool AudioPolicyService::AudioCommandThread::threadLoop() command->mStatus = af->setAudioPortConfig(&data->mConfig); } } break; + case DYN_POLICY_MIX_STATE_UPDATE: { + DynPolicyMixStateUpdateData *data = + (DynPolicyMixStateUpdateData *)command->mParam.get(); + //###ALOGV("AudioCommandThread() processing dyn policy mix state update"); + ALOGV("AudioCommandThread() processing dyn policy mix state update %s %d", + data->mRegId.string(), data->mState); + svc = mService.promote(); + if (svc == 0) { + break; + } + mLock.unlock(); + svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState); + mLock.lock(); + } break; default: ALOGW("AudioCommandThread() unknown command %d", command->mCommand); } @@ -747,6 +784,20 @@ status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand( return sendCommand(command, delayMs); } +void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand( + String8 regId, int32_t state) +{ + sp command = new AudioCommand(); + command->mCommand = DYN_POLICY_MIX_STATE_UPDATE; + DynPolicyMixStateUpdateData *data = new DynPolicyMixStateUpdateData(); + data->mRegId = regId; + data->mState = state; + command->mParam = data; + ALOGV("AudioCommandThread() sending dynamic policy mix (id=%s) state update to %d", + regId.string(), state); + sendCommand(command); +} + status_t AudioPolicyService::AudioCommandThread::sendCommand(sp& command, int delayMs) { { @@ -888,6 +939,10 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(sp& c delayMs = 1; } break; + case DYN_POLICY_MIX_STATE_UPDATE: { + + } break; + case START_TONE: case STOP_TONE: default: diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index f8dabd3..fbd8f0e 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -213,6 +213,9 @@ public: void onAudioPatchListUpdate(); void doOnAudioPatchListUpdate(); + void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); + void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state); + private: AudioPolicyService() ANDROID_API; virtual ~AudioPolicyService(); @@ -243,6 +246,7 @@ private: UPDATE_AUDIOPORT_LIST, UPDATE_AUDIOPATCH_LIST, SET_AUDIOPORT_CONFIG, + DYN_POLICY_MIX_STATE_UPDATE }; AudioCommandThread (String8 name, const wp& service); @@ -280,6 +284,7 @@ private: void updateAudioPatchListCommand(); status_t setAudioPortConfigCommand(const struct audio_port_config *config, int delayMs); + void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state); void insertCommand_l(AudioCommand *command, int delayMs = 0); private: @@ -364,6 +369,12 @@ private: struct audio_port_config mConfig; }; + class DynPolicyMixStateUpdateData : public AudioCommandData { + public: + String8 mRegId; + int32_t mState; + }; + Mutex mLock; Condition mWaitWorkCV; Vector < sp > mAudioCommands; // list of pending commands @@ -469,6 +480,7 @@ private: virtual void onAudioPortListUpdate(); virtual void onAudioPatchListUpdate(); + virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); virtual audio_unique_id_t newAudioUniqueId(); @@ -484,8 +496,9 @@ private: uid_t uid); virtual ~NotificationClient(); - void onAudioPortListUpdate(); - void onAudioPatchListUpdate(); + void onAudioPortListUpdate(); + void onAudioPatchListUpdate(); + void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); // IBinder::DeathRecipient virtual void binderDied(const wp& who); -- cgit v1.1