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
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::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::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 @@
                         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 @@
     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 @@
             delayMs = 1;
         } break;
 
+        case DYN_POLICY_MIX_STATE_UPDATE: {
+
+        } break;
+
         case START_TONE:
         case STOP_TONE:
         default: