summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioPolicy.h11
-rw-r--r--include/media/AudioSystem.h1
-rw-r--r--include/media/IAudioPolicyServiceClient.h2
-rw-r--r--media/libmedia/AudioPolicy.cpp2
-rw-r--r--media/libmedia/AudioSystem.cpp6
-rw-r--r--media/libmedia/IAudioPolicyServiceClient.cpp19
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h2
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h1
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp23
-rw-r--r--services/audiopolicy/service/AudioPolicyClientImpl.cpp6
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp55
-rw-r--r--services/audiopolicy/service/AudioPolicyService.h17
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<AttributeMatchCriterion> 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<IBinder>& 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<IAudioPolicyServiceClient>
@@ -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<SwAudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output
sp<SwAudioOutputDescriptor> 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<IBinder>& 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<AudioCommand> 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<AudioCommand>& command, int delayMs)
{
{
@@ -888,6 +939,10 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& 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<AudioPolicyService>& 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<AudioCommand> > 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<IBinder>& who);