Merge "IMediaSource: release mediabuffer after content is copied into shared memory." into nyc-dev
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/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index cbf9839..3131090 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -78,7 +78,7 @@
         virtual size_t countBuffers() = 0;
         virtual IOMX::buffer_id bufferIDAt(size_t index) const = 0;
         virtual sp<ABuffer> bufferAt(size_t index) const = 0;
-        virtual sp<NativeHandle> handleAt(size_t index) { return NULL; };
+        virtual sp<NativeHandle> handleAt(size_t index) const { return NULL; };
         virtual sp<RefBase> memRefAt(size_t index) const { return NULL; }
 
     protected:
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/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index 8376c0a..1770fb8 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "BpMediaSource"
 #include <utils/Log.h>
 
+#include <utils/CallStack.h>
+
 #include <inttypes.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -109,9 +111,16 @@
     BpMediaSource(const sp<IBinder>& impl)
         : BpInterface<IMediaSource>(impl)
     {
+        mStarted = false;
     }
 
     virtual status_t start(MetaData *params) {
+        if (mStarted) {
+            ALOGD("Source was started previously from:");
+            mStartStack.log(LOG_TAG);
+            ALOGD("Now from:");
+            CallStack stack(LOG_TAG);
+        }
         ALOGV("start");
         Parcel data, reply;
         data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
@@ -119,6 +128,10 @@
             params->writeToParcel(data);
         }
         status_t ret = remote()->transact(START, data, &reply);
+        if (ret == NO_ERROR) {
+            mStarted = true;
+            mStartStack.update();
+        }
         if (ret == NO_ERROR && params) {
             ALOGW("ignoring potentially modified MetaData from start");
             ALOGW("input:");
@@ -131,6 +144,7 @@
     }
 
     virtual status_t stop() {
+        mStarted = false;
         ALOGV("stop");
         Parcel data, reply;
         data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
@@ -205,7 +219,8 @@
     // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
     // XXX: could we use this for caching, or does metadata change on the fly?
     sp<MetaData> mMetaData;
-
+    bool mStarted;
+    CallStack mStartStack;
 };
 
 IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 44279ce..6c54e3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -746,7 +746,7 @@
                     if (!mPaused) {
                         mRenderer->pause();
                     }
-                    restartAudioFromOffload(
+                    restartAudio(
                             currentPositionUs, true /* forceNonOffload */,
                             true /* needsToCreateAudioDecoder */);
                     if (!mPaused) {
@@ -1149,7 +1149,7 @@
                     positionUs = mPreviousSeekTimeUs;
                 }
 
-                restartAudioFromOffload(
+                restartAudio(
                         positionUs, false /* forceNonOffload */,
                         reason == Renderer::kDueToError /* needsToCreateAudioDecoder */);
             }
@@ -1488,11 +1488,8 @@
     mRenderer->closeAudioSink();
 }
 
-void NuPlayer::restartAudioFromOffload(
+void NuPlayer::restartAudio(
         int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) {
-    if (!mOffloadAudio) {
-        return;
-    }
     mAudioDecoder->pause();
     mAudioDecoder.clear();
     ++mAudioDecoderGeneration;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 5e48b30..a55aa5f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -233,7 +233,7 @@
 
     void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
     void closeAudioSink();
-    void restartAudioFromOffload(
+    void restartAudio(
         int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder);
     void determineAudioModeChange();
 
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index ec33478..ba40876 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -32,6 +32,12 @@
 
 const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
 
+// Buffer Underflow/Prepare/StartServer/Overflow Marks
+const int64_t NuPlayer::RTSPSource::kUnderflowMarkUs   =  1000000ll;
+const int64_t NuPlayer::RTSPSource::kPrepareMarkUs     =  3000000ll;
+const int64_t NuPlayer::RTSPSource::kStartServerMarkUs =  5000000ll;
+const int64_t NuPlayer::RTSPSource::kOverflowMarkUs    = 10000000ll;
+
 NuPlayer::RTSPSource::RTSPSource(
         const sp<AMessage> &notify,
         const sp<IMediaHTTPService> &httpService,
@@ -51,6 +57,7 @@
       mFinalResult(OK),
       mDisconnectReplyID(0),
       mBuffering(false),
+      mInPreparationPhase(true),
       mSeekGeneration(0),
       mEOSTimeoutAudio(0),
       mEOSTimeoutVideo(0) {
@@ -127,29 +134,6 @@
     msg->postAndAwaitResponse(&dummy);
 }
 
-void NuPlayer::RTSPSource::pause() {
-    int64_t mediaDurationUs = 0;
-    getDuration(&mediaDurationUs);
-    for (size_t index = 0; index < mTracks.size(); index++) {
-        TrackInfo *info = &mTracks.editItemAt(index);
-        sp<AnotherPacketSource> source = info->mSource;
-
-        // Check if EOS or ERROR is received
-        if (source != NULL && source->isFinished(mediaDurationUs)) {
-            return;
-        }
-    }
-    if (mHandler != NULL) {
-        mHandler->pause();
-    }
-}
-
-void NuPlayer::RTSPSource::resume() {
-    if (mHandler != NULL) {
-        mHandler->resume();
-    }
-}
-
 status_t NuPlayer::RTSPSource::feedMoreTSData() {
     Mutex::Autolock _l(mBufferingLock);
     return mFinalResult;
@@ -324,6 +308,73 @@
     mHandler->seek(seekTimeUs);
 }
 
+void NuPlayer::RTSPSource::schedulePollBuffering() {
+    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
+    msg->post(1000000ll); // 1 second intervals
+}
+
+void NuPlayer::RTSPSource::checkBuffering(
+        bool *prepared, bool *underflow, bool *overflow, bool *startServer) {
+    size_t numTracks = mTracks.size();
+    size_t preparedCount, underflowCount, overflowCount, startCount;
+    preparedCount = underflowCount = overflowCount = startCount = 0;
+    for (size_t i = 0; i < numTracks; ++i) {
+        status_t finalResult;
+        TrackInfo *info = &mTracks.editItemAt(i);
+        sp<AnotherPacketSource> src = info->mSource;
+        int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
+
+        // isFinished when duration is 0 checks for EOS result only
+        if (bufferedDurationUs > kPrepareMarkUs || src->isFinished(/* duration */ 0)) {
+            ++preparedCount;
+        }
+
+        if (src->isFinished(/* duration */ 0)) {
+            ++overflowCount;
+        } else {
+            if (bufferedDurationUs < kUnderflowMarkUs) {
+                ++underflowCount;
+            }
+            if (bufferedDurationUs > kOverflowMarkUs) {
+                ++overflowCount;
+            }
+            if (bufferedDurationUs < kStartServerMarkUs) {
+                ++startCount;
+            }
+        }
+    }
+
+    *prepared    = (preparedCount == numTracks);
+    *underflow   = (underflowCount > 0);
+    *overflow    = (overflowCount == numTracks);
+    *startServer = (startCount > 0);
+}
+
+void NuPlayer::RTSPSource::onPollBuffering() {
+    bool prepared, underflow, overflow, startServer;
+    checkBuffering(&prepared, &underflow, &overflow, &startServer);
+
+    if (prepared && mInPreparationPhase) {
+        mInPreparationPhase = false;
+        notifyPrepared();
+    }
+
+    if (!mInPreparationPhase && underflow) {
+        startBufferingIfNecessary();
+    }
+
+    if (overflow && mHandler != NULL) {
+        stopBufferingIfNecessary();
+        mHandler->pause();
+    }
+
+    if (startServer && mHandler != NULL) {
+        mHandler->resume();
+    }
+
+    schedulePollBuffering();
+}
+
 void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
     if (msg->what() == kWhatDisconnect) {
         sp<AReplyToken> replyID;
@@ -348,6 +399,9 @@
 
         performSeek(seekTimeUs);
         return;
+    } else if (msg->what() == kWhatPollBuffering) {
+        onPollBuffering();
+        return;
     }
 
     CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -372,7 +426,7 @@
             }
 
             notifyFlagsChanged(flags);
-            notifyPrepared();
+            schedulePollBuffering();
             break;
         }
 
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 6438a1e..a6a7644 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -43,8 +43,6 @@
     virtual void prepareAsync();
     virtual void start();
     virtual void stop();
-    virtual void pause();
-    virtual void resume();
 
     virtual status_t feedMoreTSData();
 
@@ -65,6 +63,7 @@
         kWhatNotify          = 'noti',
         kWhatDisconnect      = 'disc',
         kWhatPerformSeek     = 'seek',
+        kWhatPollBuffering   = 'poll',
     };
 
     enum State {
@@ -79,6 +78,12 @@
         kFlagIncognito = 1,
     };
 
+    // Buffer Prepare/Underflow/Overflow/Resume Marks
+    static const int64_t kPrepareMarkUs;
+    static const int64_t kUnderflowMarkUs;
+    static const int64_t kOverflowMarkUs;
+    static const int64_t kStartServerMarkUs;
+
     struct TrackInfo {
         sp<AnotherPacketSource> mSource;
 
@@ -100,6 +105,7 @@
     sp<AReplyToken> mDisconnectReplyID;
     Mutex mBufferingLock;
     bool mBuffering;
+    bool mInPreparationPhase;
 
     sp<ALooper> mLooper;
     sp<MyHandler> mHandler;
@@ -126,6 +132,9 @@
     void finishDisconnectIfPossible();
 
     void performSeek(int64_t seekTimeUs);
+    void schedulePollBuffering();
+    void checkBuffering(bool *prepared, bool *underflow, bool *overflow, bool *startServer);
+    void onPollBuffering();
 
     bool haveSufficientDataOnAllTracks();
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index fb1f401..fbdf56f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2498,7 +2498,7 @@
         ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
 
         if (info->mNativeHandle != NULL) {
-            dst_pointer = (void *)info->mNativeHandle.get();
+            dst_pointer = (void *)info->mNativeHandle->handle();
             dst_type = ICrypto::kDestinationTypeNativeHandle;
         } else if ((mFlags & kFlagIsSecure) == 0) {
             dst_type = ICrypto::kDestinationTypeVmPointer;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index eedbb42..6fa83fa 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -235,7 +235,7 @@
         sp<AMessage> msg = new AMessage('paus', this);
         mPauseGeneration++;
         msg->setInt32("pausecheck", mPauseGeneration);
-        msg->post(kPauseDelayUs);
+        msg->post();
     }
 
     void resume() {
@@ -979,6 +979,11 @@
 
             case 'accu':
             {
+                if (mSeekPending) {
+                    ALOGV("Stale access unit.");
+                    break;
+                }
+
                 int32_t timeUpdate;
                 if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
                     size_t trackIndex;
@@ -1070,6 +1075,12 @@
                     ALOGW("This is a live stream, ignoring pause request.");
                     break;
                 }
+
+                if (mPausing) {
+                    ALOGV("This stream is already paused.");
+                    break;
+                }
+
                 mCheckPending = true;
                 ++mCheckGeneration;
                 mPausing = true;
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index 3af0956..cb7e4aa 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -37,7 +37,7 @@
 
 LOCAL_MODULE:= libmtp
 
-LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
+LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST -Wall -Wextra -Werror
 
 LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libusbhost libbinder
 
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index d0ec2a6..0381edf 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -456,7 +456,7 @@
         // look at the length field to see if the data spans multiple packets
         uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
         allocate(totalLength);
-        while (totalLength > length) {
+        while (totalLength > static_cast<uint32_t>(length)) {
             request->buffer = mBuffer + length;
             request->buffer_length = totalLength - length;
             int ret = transfer(request);
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 7d7ea13..a398aca 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -505,6 +505,7 @@
     int remaining = size;
     mRequest.reset();
     mRequest.setParameter(1, handle);
+    bool error = false;
     if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
         // send data header
         writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
@@ -514,7 +515,9 @@
         while (remaining > 0) {
             int count = read(srcFD, buffer, sizeof(buffer));
             if (count > 0) {
-                int written = mData.write(mRequestOut, buffer, count);
+                if (mData.write(mRequestOut, buffer, count) < 0) {
+                    error = true;
+                }
                 // FIXME check error
                 remaining -= count;
             } else {
@@ -523,7 +526,7 @@
         }
     }
     MtpResponseCode ret = readResponse();
-    return (remaining == 0 && ret == MTP_RESPONSE_OK);
+    return (remaining == 0 && ret == MTP_RESPONSE_OK && !error);
 }
 
 bool MtpDevice::deleteObject(MtpObjectHandle handle) {
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index bab1335..35ecb4f 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -69,7 +69,7 @@
     char buffer[500];
     char* bufptr = buffer;
 
-    for (int i = 0; i < mPacketSize; i++) {
+    for (size_t i = 0; i < mPacketSize; i++) {
         sprintf(bufptr, "%02X ", mBuffer[i]);
         bufptr += strlen(bufptr);
         if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index d58e2a4..2be2d79 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -544,7 +544,7 @@
     MtpPropertyValue* result = new MtpPropertyValue[length];
     for (uint32_t i = 0; i < length; i++)
         if (!readValue(packet, result[i])) {
-            delete result;
+            delete [] result;
             return NULL;
         }
     return result;
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
index 40b11b0..471967f 100644
--- a/media/mtp/MtpRequestPacket.cpp
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -44,11 +44,12 @@
     }
 
     // request packet should have 12 byte header followed by 0 to 5 32-bit arguments
-    if (ret >= MTP_CONTAINER_HEADER_SIZE
-            && ret <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
-            && ((ret - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
-        mPacketSize = ret;
-        mParameterCount = (ret - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
+    const size_t read_size = static_cast<size_t>(ret);
+    if (read_size >= MTP_CONTAINER_HEADER_SIZE
+            && read_size <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
+            && ((read_size - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
+        mPacketSize = read_size;
+        mParameterCount = (read_size - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
     } else {
         ALOGE("Malformed MTP request packet");
         ret = -1;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 3e0f239..90f1a77 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -923,9 +923,7 @@
     if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // image bit depth
     if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // parent
     if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
-    uint16_t associationType = temp16;
     if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
-    uint32_t associationDesc = temp32;        // association desc
     if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;  // sequence number
     MtpStringBuffer name, created, modified;
     if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER;    // file name
@@ -1102,7 +1100,6 @@
         }
         strcpy(fileSpot, name);
 
-        int type = entry->d_type;
         if (entry->d_type == DT_DIR) {
             deleteRecursive(pathbuf);
             rmdir(pathbuf);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e056ef2..e3036c6 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -468,6 +468,7 @@
         {AUDIO_DEVICE_OUT_AUX_LINE,         "AUX_LINE"},
         {AUDIO_DEVICE_OUT_SPEAKER_SAFE,     "SPEAKER_SAFE"},
         {AUDIO_DEVICE_OUT_IP,               "IP"},
+        {AUDIO_DEVICE_OUT_BUS,              "BUS"},
         {AUDIO_DEVICE_NONE,                 "NONE"},       // must be last
     }, mappingsIn[] = {
         {AUDIO_DEVICE_IN_COMMUNICATION,     "COMMUNICATION"},
@@ -491,6 +492,7 @@
         {AUDIO_DEVICE_IN_BLUETOOTH_A2DP,    "BLUETOOTH_A2DP"},
         {AUDIO_DEVICE_IN_LOOPBACK,          "LOOPBACK"},
         {AUDIO_DEVICE_IN_IP,                "IP"},
+        {AUDIO_DEVICE_IN_BUS,               "BUS"},
         {AUDIO_DEVICE_NONE,                 "NONE"},        // must be last
     };
     String8 result;
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/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index f8439be..dd3f8ae 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -71,9 +71,11 @@
 
     audio_module_handle_t getModuleHandle() const;
 
+    audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
+    void setPatchHandle(audio_patch_handle_t handle) { mPatchHandle = handle; };
+
     sp<AudioPort>       mPort;
     audio_devices_t mDevice;                   // current device this output is routed to
-    audio_patch_handle_t mPatchHandle;
     uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
     nsecs_t mStopTime[AUDIO_STREAM_CNT];
     float mCurVolume[AUDIO_STREAM_CNT];   // current stream volume in dB
@@ -83,6 +85,7 @@
     AudioPolicyClientInterface *mClientInterface;
 
 protected:
+    audio_patch_handle_t mPatchHandle;
     audio_port_handle_t mId;
 };
 
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/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 5d0f03f..0fe1a84 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -34,7 +34,7 @@
 AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
                                              AudioPolicyClientInterface *clientInterface)
     : mPort(port), mDevice(AUDIO_DEVICE_NONE),
-      mPatchHandle(0), mClientInterface(clientInterface), mId(0)
+      mClientInterface(clientInterface), mPatchHandle(0), mId(0)
 {
     // clear usage count for all stream types
     for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
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/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index f613f94..c6ed53e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -50,6 +50,7 @@
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -72,6 +73,7 @@
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
         MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
+        MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
 };
 
 template<>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index c65de92..8221496 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -1,5 +1,7 @@
 LOCAL_PATH := $(call my-dir)
 
+ifneq ($(USE_CUSTOM_PARAMETER_FRAMEWORK), true)
+
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
@@ -33,3 +35,4 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+endif # ifneq ($(USE_CUSTOM_PARAMETER_FRAMEWORK), true)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 758673b..8ef6b1fc 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);
@@ -3939,7 +3939,7 @@
 
     nextAudioPortGeneration();
 
-    ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+    ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(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);
@@ -4153,12 +4153,12 @@
 {
     audio_devices_t device = AUDIO_DEVICE_NONE;
 
-    ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+    ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
     if (index >= 0) {
         sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
         if (patchDesc->mUid != mUidCached) {
             ALOGV("getNewOutputDevice() device %08x forced by patch %d",
-                  outputDesc->device(), outputDesc->mPatchHandle);
+                  outputDesc->device(), outputDesc->getPatchHandle());
             return outputDesc->device();
         }
     }
@@ -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;
         }
     }
@@ -4513,7 +4513,7 @@
     // Doing this check here allows the caller to call setOutputDevice() without conditions
     if ((device == AUDIO_DEVICE_NONE || device == prevDevice) &&
         !force &&
-        outputDesc->mPatchHandle != 0) {
+        outputDesc->getPatchHandle() != 0) {
         ALOGV("setOutputDevice() setting same device 0x%04x or null device", device);
         return muteWaitMs;
     }
@@ -4540,7 +4540,7 @@
             if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) {
                 index = mAudioPatches.indexOfKey(*patchHandle);
             } else {
-                index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+                index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
             }
             sp< AudioPatch> patchDesc;
             audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -4566,7 +4566,7 @@
                 if (patchHandle) {
                     *patchHandle = patchDesc->mHandle;
                 }
-                outputDesc->mPatchHandle = patchDesc->mHandle;
+                outputDesc->setPatchHandle(patchDesc->mHandle);
                 nextAudioPortGeneration();
                 mpClientInterface->onAudioPatchListUpdate();
             }
@@ -4601,7 +4601,7 @@
     if (patchHandle) {
         index = mAudioPatches.indexOfKey(*patchHandle);
     } else {
-        index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+        index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
     }
     if (index < 0) {
         return INVALID_OPERATION;
@@ -4609,7 +4609,7 @@
     sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
     status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs);
     ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status);
-    outputDesc->mPatchHandle = 0;
+    outputDesc->setPatchHandle(0);
     removeAudioPatch(patchDesc->mHandle);
     nextAudioPortGeneration();
     mpClientInterface->onAudioPatchListUpdate();
@@ -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
diff --git a/services/mediadrm/mediadrmserver.rc b/services/mediadrm/mediadrmserver.rc
index c22ec7c..374d24b 100644
--- a/services/mediadrm/mediadrmserver.rc
+++ b/services/mediadrm/mediadrmserver.rc
@@ -1,5 +1,5 @@
 service mediadrm /system/bin/mediadrmserver
     class main
-    user mediadrm
-    group drmrpc
+    user media
+    group mediadrm drmrpc
     ioprio rt 4