Send audio patch in recording callback

Remove direct access to patch handle in AudioInputDescriptor, replace with
  set / get functions.
Add interface for AudioSession to query configuration from enclosing
  input descriptor.
When input descriptor's patch handle changes during a recording, propagate
  the change through the recording notification callback.

Bug 26798796

Change-Id: Ia1395d44da7ccfe69ca46877638d1eb49b3935ad
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index a171493..c769a62 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -97,6 +97,7 @@
 
 // definitions for audio recording configuration updates
 // which update type is reported
+#define RECORD_CONFIG_EVENT_NONE -1
 #define RECORD_CONFIG_EVENT_START 1
 #define RECORD_CONFIG_EVENT_STOP  0
 
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 7011858..e3f2d60 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -32,8 +32,8 @@
 typedef void (*audio_error_callback)(status_t err);
 typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
 typedef void (*record_config_callback)(int event, int session, int source,
-                const audio_config_base_t *clientConfig,
-                const audio_config_base_t *deviceConfig);
+                const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+                audio_patch_handle_t patchHandle);
 
 class IAudioFlinger;
 class IAudioPolicyService;
@@ -427,7 +427,7 @@
         virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
         virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
                         audio_source_t source, const audio_config_base_t *clientConfig,
-                        const audio_config_base_t *deviceConfig);
+                        const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
 
     private:
         Mutex                               mLock;
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
index 8c3459d..d94ad00 100644
--- a/include/media/IAudioPolicyServiceClient.h
+++ b/include/media/IAudioPolicyServiceClient.h
@@ -41,7 +41,8 @@
     virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
             audio_source_t source,
             const audio_config_base_t *clientConfig,
-            const audio_config_base_t *deviceConfig) = 0;
+            const audio_config_base_t *deviceConfig,
+            audio_patch_handle_t patchHandle) = 0;
 };
 
 
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 1607af5..56c600d 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -1246,7 +1246,8 @@
 
 void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
         int event, audio_session_t session, audio_source_t source,
-        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig) {
+        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+        audio_patch_handle_t patchHandle) {
     record_config_callback cb = NULL;
     {
         Mutex::Autolock _l(AudioSystem::gLock);
@@ -1254,7 +1255,7 @@
     }
 
     if (cb != NULL) {
-        cb(event, session, source, clientConfig, deviceConfig);
+        cb(event, session, source, clientConfig, deviceConfig, patchHandle);
     }
 }
 
diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp
index 0aeaf3c..5f931e5 100644
--- a/media/libmedia/IAudioPolicyServiceClient.cpp
+++ b/media/libmedia/IAudioPolicyServiceClient.cpp
@@ -82,7 +82,7 @@
 
     void onRecordingConfigurationUpdate(int event, audio_session_t session,
             audio_source_t source, const audio_config_base_t *clientConfig,
-            const audio_config_base_t *deviceConfig) {
+            const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
         data.writeInt32(event);
@@ -90,6 +90,7 @@
         data.writeInt32(source);
         writeAudioConfigBaseToParcel(data, clientConfig);
         writeAudioConfigBaseToParcel(data, deviceConfig);
+        data.writeInt32(patchHandle);
         remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
     }
 };
@@ -128,7 +129,9 @@
             audio_config_base_t deviceConfig;
             readAudioConfigBaseFromParcel(data, &clientConfig);
             readAudioConfigBaseFromParcel(data, &deviceConfig);
-            onRecordingConfigurationUpdate(event, session, source, &clientConfig, &deviceConfig);
+            audio_patch_handle_t patchHandle = (audio_patch_handle_t) data.readInt32();
+            onRecordingConfigurationUpdate(event, session, source, &clientConfig, &deviceConfig,
+                    patchHandle);
             return NO_ERROR;
         } break;
     default:
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 40ca899..ce1ae4d 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -339,7 +339,8 @@
     virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
                     audio_source_t source,
                     const struct audio_config_base *clientConfig,
-                    const struct audio_config_base *deviceConfig) = 0;
+                    const struct audio_config_base *deviceConfig,
+                    audio_patch_handle_t patchHandle) = 0;
 };
 
 extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 77c0d07..46309ed 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -18,6 +18,7 @@
 
 #include "AudioPort.h"
 #include "AudioSession.h"
+#include "AudioSessionInfoProvider.h"
 #include <utils/Errors.h>
 #include <system/audio.h>
 #include <utils/SortedVector.h>
@@ -30,7 +31,7 @@
 
 // descriptor for audio inputs. Used to maintain current configuration of each opened audio input
 // and keep track of the usage of this input.
-class AudioInputDescriptor: public AudioPortConfig
+class AudioInputDescriptor: public AudioPortConfig, public AudioSessionInfoProvider
 {
 public:
     AudioInputDescriptor(const sp<IOProfile>& profile);
@@ -44,7 +45,6 @@
     audio_io_handle_t             mIoHandle;       // input handle
     audio_devices_t               mDevice;         // current device this input is routed to
     AudioMix                      *mPolicyMix;     // non NULL when used by a dynamic policy
-    audio_patch_handle_t          mPatchHandle;
     const sp<IOProfile>           mProfile;        // I/O profile this output derives from
 
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -65,7 +65,14 @@
     sp<AudioSession> getAudioSession(audio_session_t session) const;
     AudioSessionCollection getActiveAudioSessions() const;
 
+    // implementation of AudioSessionInfoProvider
+    virtual audio_config_base_t getConfig() const;
+    virtual audio_patch_handle_t getPatchHandle() const;
+
+    void setPatchHandle(audio_patch_handle_t handle);
+
 private:
+    audio_patch_handle_t          mPatchHandle;
     audio_port_handle_t           mId;
     // audio sessions attached to this input
     AudioSessionCollection        mSessions;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
index 799410b..388c25d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
@@ -22,12 +22,13 @@
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <media/AudioPolicy.h>
+#include "AudioSessionInfoProvider.h"
 
 namespace android {
 
 class AudioPolicyClientInterface;
 
-class AudioSession : public RefBase
+class AudioSession : public RefBase, public AudioSessionInfoUpdateListener
 {
 public:
     AudioSession(audio_session_t session,
@@ -58,14 +59,14 @@
     uint32_t changeOpenCount(int delta);
     uint32_t changeActiveCount(int delta);
 
-    void setDeviceConfig(audio_format_t format, uint32_t sampleRate,
-            audio_channel_mask_t channelMask);
+    void setInfoProvider(AudioSessionInfoProvider *provider);
+    // implementation of AudioSessionInfoUpdateListener
+    virtual void onSessionInfoUpdate() const;
 
 private:
     const audio_session_t mSession;
     const audio_source_t mInputSource;
     const struct audio_config_base mConfig;
-          struct audio_config_base mDeviceConfig;
     const audio_input_flags_t mFlags;
     const uid_t mUid;
     bool  mIsSoundTrigger;
@@ -73,14 +74,17 @@
     uint32_t  mActiveCount;
     AudioMix* mPolicyMix; // non NULL when used by a dynamic policy
     AudioPolicyClientInterface* mClientInterface;
+    const AudioSessionInfoProvider* mInfoProvider;
 };
 
 class AudioSessionCollection :
-    public DefaultKeyedVector<audio_session_t, sp<AudioSession> >
+    public DefaultKeyedVector<audio_session_t, sp<AudioSession> >,
+    public AudioSessionInfoUpdateListener
 {
 public:
     status_t addSession(audio_session_t session,
-                             const sp<AudioSession>& audioSession);
+                             const sp<AudioSession>& audioSession,
+                             AudioSessionInfoProvider *provider);
 
     status_t removeSession(audio_session_t session);
 
@@ -90,6 +94,9 @@
     bool hasActiveSession() const;
     bool isSourceActive(audio_source_t source) const;
 
+    // implementation of AudioSessionInfoUpdateListener
+    virtual void onSessionInfoUpdate() const;
+
     status_t dump(int fd, int spaces) const;
 };
 
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h b/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h
new file mode 100644
index 0000000..e0037fc
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#pragma once
+
+namespace android {
+
+/**
+ * Interface for input descriptors to implement so dependent audio sessions can query information
+ * about their context
+ */
+class AudioSessionInfoProvider
+{
+public:
+    virtual ~AudioSessionInfoProvider() {};
+
+    virtual audio_config_base_t getConfig() const = 0;
+
+    virtual audio_patch_handle_t getPatchHandle() const = 0;
+
+};
+
+class AudioSessionInfoUpdateListener
+{
+public:
+    virtual ~AudioSessionInfoUpdateListener() {};
+
+    virtual void onSessionInfoUpdate() const = 0;;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 5523aff..d4992b0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -28,8 +28,8 @@
 
 AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
     : mIoHandle(0),
-      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0),
-      mProfile(profile), mId(0)
+      mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
+      mProfile(profile), mPatchHandle(0), mId(0)
 {
     if (profile != NULL) {
         profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -150,14 +150,31 @@
 
 status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
                          const sp<AudioSession>& audioSession) {
-    audioSession->setDeviceConfig(mFormat, mSamplingRate, mChannelMask);
-    return mSessions.addSession(session, audioSession);
+    return mSessions.addSession(session, audioSession, /*AudioSessionInfoProvider*/this);
 }
 
 status_t AudioInputDescriptor::removeAudioSession(audio_session_t session) {
     return mSessions.removeSession(session);
 }
 
+audio_port_handle_t AudioInputDescriptor::getPatchHandle() const
+{
+    return mPatchHandle;
+}
+
+void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
+{
+    mPatchHandle = handle;
+    mSessions.onSessionInfoUpdate();
+}
+
+audio_config_base_t AudioInputDescriptor::getConfig() const
+{
+    const audio_config_base_t config = { .sample_rate = mSamplingRate, .channel_mask = mChannelMask,
+            .format = mFormat };
+    return config;
+}
+
 status_t AudioInputDescriptor::dump(int fd)
 {
     const size_t SIZE = 256;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index 2a0b477..ce9c170 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -38,9 +38,9 @@
                            AudioPolicyClientInterface *clientInterface) :
     mSession(session), mInputSource(inputSource),
     mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
-    mDeviceConfig(AUDIO_CONFIG_BASE_INITIALIZER),
     mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
-    mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface)
+    mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
+    mInfoProvider(NULL)
 {
 }
 
@@ -66,25 +66,31 @@
     }
     mActiveCount += delta;
     ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
+    int event = RECORD_CONFIG_EVENT_NONE;
 
     if ((oldActiveCount == 0) && (mActiveCount > 0)) {
-        // if input maps to a dynamic policy with an activity listener, notify of state change
-        if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
-        {
-            mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
-                    MIX_STATE_MIXING);
-        }
-        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
-                mSession, mInputSource, &mConfig, &mDeviceConfig);
+        event = RECORD_CONFIG_EVENT_START;
     } else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
+        event = RECORD_CONFIG_EVENT_STOP;
+    }
+
+    if (event != RECORD_CONFIG_EVENT_NONE) {
+        // Dynamic policy callback:
         // if input maps to a dynamic policy with an activity listener, notify of state change
         if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
         {
             mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
-                    MIX_STATE_IDLE);
+                    (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
         }
-        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP,
-                mSession, mInputSource, &mConfig, &mDeviceConfig);
+
+        // Recording configuration callback:
+        const AudioSessionInfoProvider* provider = mInfoProvider;
+        const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
+                AUDIO_CONFIG_BASE_INITIALIZER;
+        const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
+                AUDIO_PATCH_HANDLE_NONE;
+        mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
+                &mConfig, &deviceConfig, patchHandle);
     }
 
     return mActiveCount;
@@ -104,11 +110,24 @@
     return false;
 }
 
-void AudioSession::setDeviceConfig(audio_format_t format, uint32_t sampleRate,
-            audio_channel_mask_t channelMask) {
-    mDeviceConfig.format = format;
-    mDeviceConfig.sample_rate = sampleRate;
-    mDeviceConfig.channel_mask = channelMask;
+void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
+{
+    mInfoProvider = provider;
+}
+
+void AudioSession::onSessionInfoUpdate() const
+{
+    if (mActiveCount > 0) {
+        // resend the callback after requerying the informations from the info provider
+        const AudioSessionInfoProvider* provider = mInfoProvider;
+        const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
+                AUDIO_CONFIG_BASE_INITIALIZER;
+        const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
+                AUDIO_PATCH_HANDLE_NONE;
+        mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
+                mSession, mInputSource,
+                &mConfig, &deviceConfig, patchHandle);
+    }
 }
 
 status_t AudioSession::dump(int fd, int spaces, int index) const
@@ -145,7 +164,8 @@
 }
 
 status_t AudioSessionCollection::addSession(audio_session_t session,
-                                         const sp<AudioSession>& audioSession)
+                                         const sp<AudioSession>& audioSession,
+                                         AudioSessionInfoProvider *provider)
 {
     ssize_t index = indexOfKey(session);
 
@@ -153,6 +173,7 @@
         ALOGW("addSession() session %d already in", session);
         return ALREADY_EXISTS;
     }
+    audioSession->setInfoProvider(provider);
     add(session, audioSession);
     ALOGV("addSession() session %d  client %d source %d",
             session, audioSession->uid(), audioSession->inputSource());
@@ -168,6 +189,7 @@
         return ALREADY_EXISTS;
     }
     ALOGV("removeSession() session %d", session);
+    valueAt(index)->setInfoProvider(NULL);
     removeItemsAt(index);
     return NO_ERROR;
 }
@@ -214,6 +236,13 @@
     return false;
 }
 
+void AudioSessionCollection::onSessionInfoUpdate() const
+{
+    for (size_t i = 0; i < size(); i++) {
+        valueAt(i)->onSessionInfoUpdate();
+    }
+}
+
 
 status_t AudioSessionCollection::dump(int fd, int spaces) const
 {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 758673b..478dc47 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1765,7 +1765,7 @@
 
     for(size_t input_index = 0; input_index < mInputs.size(); input_index++) {
         sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index);
-        ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+        ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
         if (patch_index >= 0) {
             sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
             status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -3968,7 +3968,7 @@
 
     nextAudioPortGeneration();
 
-    ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+    ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
         status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -4214,12 +4214,12 @@
 {
     sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input);
 
-    ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+    ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
         if (patchDesc->mUid != mUidCached) {
             ALOGV("getNewInputDevice() device %08x forced by patch %d",
-                  inputDesc->mDevice, inputDesc->mPatchHandle);
+                  inputDesc->mDevice, inputDesc->getPatchHandle());
             return inputDesc->mDevice;
         }
     }
@@ -4645,7 +4645,7 @@
             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) {
                 index = mAudioPatches.indexOfKey(*patchHandle);
             } else {
-                index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+                index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
             }
             sp< AudioPatch> patchDesc;
             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -4670,7 +4670,7 @@
                 if (patchHandle) {
                     *patchHandle = patchDesc->mHandle;
                 }
-                inputDesc->mPatchHandle = patchDesc->mHandle;
+                inputDesc->setPatchHandle(patchDesc->mHandle);
                 nextAudioPortGeneration();
                 mpClientInterface->onAudioPatchListUpdate();
             }
@@ -4687,7 +4687,7 @@
     if (patchHandle) {
         index = mAudioPatches.indexOfKey(*patchHandle);
     } else {
-        index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+        index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
     }
     if (index < 0) {
         return INVALID_OPERATION;
@@ -4695,7 +4695,7 @@
     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
     ALOGV("resetInputDevice() releaseAudioPatch returned %d", status);
-    inputDesc->mPatchHandle = 0;
+    inputDesc->setPatchHandle(0);
     removeAudioPatch(patchDesc->mHandle);
     nextAudioPortGeneration();
     mpClientInterface->onAudioPatchListUpdate();
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index ce6b2dc..c4790b5 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -221,10 +221,11 @@
 
 void AudioPolicyService::AudioPolicyClient::onRecordingConfigurationUpdate(
         int event, audio_session_t session, audio_source_t source,
-        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+        audio_patch_handle_t patchHandle)
 {
     mAudioPolicyService->onRecordingConfigurationUpdate(event, session, source,
-            clientConfig, deviceConfig);
+            clientConfig, deviceConfig, patchHandle);
 }
 
 audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId()
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 45f260a..94e0701 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -240,20 +240,20 @@
 
 void AudioPolicyService::onRecordingConfigurationUpdate(int event, audio_session_t session,
         audio_source_t source, const audio_config_base_t *clientConfig,
-        const audio_config_base_t *deviceConfig)
+        const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
 {
     mOutputCommandThread->recordingConfigurationUpdateCommand(event, session, source,
-            clientConfig, deviceConfig);
+            clientConfig, deviceConfig, patchHandle);
 }
 
 void AudioPolicyService::doOnRecordingConfigurationUpdate(int event, audio_session_t session,
         audio_source_t source, const audio_config_base_t *clientConfig,
-        const audio_config_base_t *deviceConfig)
+        const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
 {
     Mutex::Autolock _l(mNotificationClientsLock);
     for (size_t i = 0; i < mNotificationClients.size(); i++) {
         mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, session, source,
-                clientConfig, deviceConfig);
+                clientConfig, deviceConfig, patchHandle);
     }
 }
 
@@ -321,11 +321,12 @@
 
 void AudioPolicyService::NotificationClient::onRecordingConfigurationUpdate(
         int event, audio_session_t session, audio_source_t source,
-        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+        audio_patch_handle_t patchHandle)
 {
     if (mAudioPolicyServiceClient != 0) {
         mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, session, source,
-                clientConfig, deviceConfig);
+                clientConfig, deviceConfig, patchHandle);
     }
 }
 
@@ -607,7 +608,8 @@
                     }
                     mLock.unlock();
                     svc->doOnRecordingConfigurationUpdate(data->mEvent, data->mSession,
-                            data->mSource, &data->mClientConfig, &data->mDeviceConfig);
+                            data->mSource, &data->mClientConfig, &data->mDeviceConfig,
+                            data->mPatchHandle);
                     mLock.lock();
                     } break;
                 default:
@@ -872,7 +874,8 @@
 
 void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand(
         int event, audio_session_t session, audio_source_t source,
-        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+        const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+        audio_patch_handle_t patchHandle)
 {
     sp<AudioCommand>command = new AudioCommand();
     command->mCommand = RECORDING_CONFIGURATION_UPDATE;
@@ -882,6 +885,7 @@
     data->mSource = source;
     data->mClientConfig = *clientConfig;
     data->mDeviceConfig = *deviceConfig;
+    data->mPatchHandle = patchHandle;
     command->mParam = data;
     ALOGV("AudioCommandThread() adding recording configuration update event %d, source %d",
             event, source);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 7089014..8d15eac 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -230,10 +230,10 @@
             void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
             void onRecordingConfigurationUpdate(int event, audio_session_t session,
                     audio_source_t source, const audio_config_base_t *clientConfig,
-                    const audio_config_base_t *deviceConfig);
+                    const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
             void doOnRecordingConfigurationUpdate(int event, audio_session_t session,
                     audio_source_t source, const audio_config_base_t *clientConfig,
-                    const audio_config_base_t *deviceConfig);
+                    const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
 
 private:
                         AudioPolicyService() ANDROID_API;
@@ -309,7 +309,8 @@
                                                         int event, audio_session_t session,
                                                         audio_source_t source,
                                                         const audio_config_base_t *clientConfig,
-                                                        const audio_config_base_t *deviceConfig);
+                                                        const audio_config_base_t *deviceConfig,
+                                                        audio_patch_handle_t patchHandle);
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
 
     private:
@@ -407,6 +408,7 @@
             audio_source_t mSource;
             struct audio_config_base mClientConfig;
             struct audio_config_base mDeviceConfig;
+            audio_patch_handle_t mPatchHandle;
         };
 
         Mutex   mLock;
@@ -518,7 +520,7 @@
         virtual void onRecordingConfigurationUpdate(int event,
                         audio_session_t session, audio_source_t source,
                         const audio_config_base_t *clientConfig,
-                        const audio_config_base_t *deviceConfig);
+                        const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
 
         virtual audio_unique_id_t newAudioUniqueId();
 
@@ -541,7 +543,8 @@
                                         int event, audio_session_t session,
                                         audio_source_t source,
                                         const audio_config_base_t *clientConfig,
-                                        const audio_config_base_t *deviceConfig);
+                                        const audio_config_base_t *deviceConfig,
+                                        audio_patch_handle_t patchHandle);
                             void      setAudioPortCallbacksEnabled(bool enabled);
 
                 // IBinder::DeathRecipient