Merge "opus: Support for > 2 channels"
diff --git a/camera/camera2/ICameraDeviceUser.cpp b/camera/camera2/ICameraDeviceUser.cpp
index 35345d2..277b5db 100644
--- a/camera/camera2/ICameraDeviceUser.cpp
+++ b/camera/camera2/ICameraDeviceUser.cpp
@@ -107,7 +107,7 @@
             }
         }
 
-	if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+	if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
             res = FAILED_TRANSACTION;
         }
         return res;
@@ -147,7 +147,7 @@
                 resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
-        if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
+        if ((res < NO_ERROR) || (resFrameNumber != NO_ERROR)) {
             res = FAILED_TRANSACTION;
         }
         return res;
@@ -167,7 +167,7 @@
         status_t resFrameNumber = BAD_VALUE;
         if (reply.readInt32() != 0) {
             if (lastFrameNumber != NULL) {
-                res = reply.readInt64(lastFrameNumber);
+                resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
         if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
@@ -296,7 +296,7 @@
         status_t resFrameNumber = BAD_VALUE;
         if (reply.readInt32() != 0) {
             if (lastFrameNumber != NULL) {
-                res = reply.readInt64(lastFrameNumber);
+                resFrameNumber = reply.readInt64(lastFrameNumber);
             }
         }
         if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) {
diff --git a/cmds/screenrecord/TextRenderer.cpp b/cmds/screenrecord/TextRenderer.cpp
index 6a9176b..01f73e0 100644
--- a/cmds/screenrecord/TextRenderer.cpp
+++ b/cmds/screenrecord/TextRenderer.cpp
@@ -21,6 +21,8 @@
 #include "TextRenderer.h"
 
 #include <assert.h>
+#include <malloc.h>
+#include <string.h>
 
 namespace android {
 #include "FontBitmap.h"
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index 1b2f792..4b2f980 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -332,7 +332,7 @@
 
         size_t j = 0;
         sp<ABuffer> buffer;
-        while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
+        while (format->findBuffer(AStringPrintf("csd-%d", j).c_str(), &buffer)) {
             state->mCSD.push_back(buffer);
 
             ++j;
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
index 48b0afe..933464f 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -58,8 +58,7 @@
     $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \
     $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \
     $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \
-    $(LOCAL_PATH)/include \
-    external/openssl/include
+    $(LOCAL_PATH)/include
 
 LOCAL_MODULE_RELATIVE_PATH := drm
 
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
index 6c5d3cf..3b4c8b4 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
@@ -20,9 +20,6 @@
 LOCAL_SRC_FILES := \
     FwdLockGlue.c
 
-LOCAL_C_INCLUDES := \
-    external/openssl/include
-
 LOCAL_SHARED_LIBRARIES := libcrypto
 
 LOCAL_MODULE := libfwdlock-common
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
index 8f08c88..2f51f0c 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
@@ -21,8 +21,7 @@
     FwdLockConv.c
 
 LOCAL_C_INCLUDES := \
-    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common \
-    external/openssl/include
+    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common
 
 LOCAL_SHARED_LIBRARIES := libcrypto
 
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
index 7b493c3..3399ae5 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
@@ -21,8 +21,7 @@
     FwdLockFile.c
 
 LOCAL_C_INCLUDES := \
-    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common \
-    external/openssl/include
+    frameworks/av/drm/libdrmframework/plugins/forward-lock/internal-format/common
 
 LOCAL_SHARED_LIBRARIES := libcrypto
 
diff --git a/drm/mediadrm/plugins/clearkey/Android.mk b/drm/mediadrm/plugins/clearkey/Android.mk
index b713a7f..2efdcf5 100644
--- a/drm/mediadrm/plugins/clearkey/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/Android.mk
@@ -32,7 +32,6 @@
 
 LOCAL_C_INCLUDES := \
     external/jsmn \
-    external/openssl/include \
     frameworks/av/drm/mediadrm/plugins/clearkey \
     frameworks/av/include \
     frameworks/native/include \
diff --git a/drm/mediadrm/plugins/clearkey/tests/Android.mk b/drm/mediadrm/plugins/clearkey/tests/Android.mk
index 80f94e0..392f218 100644
--- a/drm/mediadrm/plugins/clearkey/tests/Android.mk
+++ b/drm/mediadrm/plugins/clearkey/tests/Android.mk
@@ -29,7 +29,6 @@
 
 LOCAL_C_INCLUDES := \
     external/jsmn \
-    external/openssl/include \
     frameworks/av/drm/mediadrm/plugins/clearkey \
     frameworks/av/include \
     frameworks/native/include \
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 843a354..2ab3dd6 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -201,7 +201,7 @@
     // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
     //
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
-                                                const char *device_address);
+                                             const char *device_address, const char *device_name);
     static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                 const char *device_address);
     static status_t setPhoneState(audio_mode_t state);
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index c98c475..fecc6f1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -44,7 +44,8 @@
     //
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
-                                              const char *device_address) = 0;
+                                              const char *device_address,
+                                              const char *device_name) = 0;
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                   const char *device_address) = 0;
     virtual status_t setPhoneState(audio_mode_t state) = 0;
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index dd62b56..49a3d61 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -52,17 +52,6 @@
     virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0)
             = 0;
 
-    virtual status_t         decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
-
-    virtual status_t         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
-                                    int* pNumChannels, audio_format_t* pFormat,
-                                    const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
     virtual sp<IOMX>            getOMX() = 0;
     virtual sp<ICrypto>         makeCrypto() = 0;
     virtual sp<IDrm>            makeDrm() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 0fc7dcf..4a6bf28 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -88,7 +88,6 @@
 
         virtual             ~AudioSink() {}
         virtual bool        ready() const = 0; // audio output is open and ready
-        virtual bool        realtime() const = 0; // audio output is real-time output
         virtual ssize_t     bufferSize() const = 0;
         virtual ssize_t     frameCount() const = 0;
         virtual ssize_t     channelCount() const = 0;
diff --git a/include/media/SoundPool.h b/include/media/SoundPool.h
deleted file mode 100644
index 5830475..0000000
--- a/include/media/SoundPool.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef SOUNDPOOL_H_
-#define SOUNDPOOL_H_
-
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-#include <media/AudioTrack.h>
-#include <binder/MemoryHeapBase.h>
-#include <binder/MemoryBase.h>
-
-namespace android {
-
-static const int IDLE_PRIORITY = -1;
-
-// forward declarations
-class SoundEvent;
-class SoundPoolThread;
-class SoundPool;
-
-// for queued events
-class SoundPoolEvent {
-public:
-    SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
-        mMsg(msg), mArg1(arg1), mArg2(arg2) {}
-    int         mMsg;
-    int         mArg1;
-    int         mArg2;
-    enum MessageType { INVALID, SAMPLE_LOADED };
-};
-
-// callback function prototype
-typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
-
-// tracks samples used by application
-class Sample  : public RefBase {
-public:
-    enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
-    Sample(int sampleID, const char* url);
-    Sample(int sampleID, int fd, int64_t offset, int64_t length);
-    ~Sample();
-    int sampleID() { return mSampleID; }
-    int numChannels() { return mNumChannels; }
-    int sampleRate() { return mSampleRate; }
-    audio_format_t format() { return mFormat; }
-    size_t size() { return mSize; }
-    int state() { return mState; }
-    uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
-    status_t doLoad();
-    void startLoad() { mState = LOADING; }
-    sp<IMemory> getIMemory() { return mData; }
-
-    // hack
-    void init(int numChannels, int sampleRate, audio_format_t format, size_t size,
-            sp<IMemory> data ) {
-        mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size;
-            mData = data; }
-
-private:
-    void init();
-
-    size_t              mSize;
-    volatile int32_t    mRefCount;
-    uint16_t            mSampleID;
-    uint16_t            mSampleRate;
-    uint8_t             mState : 3;
-    uint8_t             mNumChannels : 2;
-    audio_format_t      mFormat;
-    int                 mFd;
-    int64_t             mOffset;
-    int64_t             mLength;
-    char*               mUrl;
-    sp<IMemory>         mData;
-    sp<MemoryHeapBase>  mHeap;
-};
-
-// stores pending events for stolen channels
-class SoundEvent
-{
-public:
-    SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
-            mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
-    void set(const sp<Sample>& sample, int channelID, float leftVolume,
-            float rightVolume, int priority, int loop, float rate);
-    sp<Sample>      sample() { return mSample; }
-    int             channelID() { return mChannelID; }
-    float           leftVolume() { return mLeftVolume; }
-    float           rightVolume() { return mRightVolume; }
-    int             priority() { return mPriority; }
-    int             loop() { return mLoop; }
-    float           rate() { return mRate; }
-    void            clear() { mChannelID = 0; mSample.clear(); }
-
-protected:
-    sp<Sample>      mSample;
-    int             mChannelID;
-    float           mLeftVolume;
-    float           mRightVolume;
-    int             mPriority;
-    int             mLoop;
-    float           mRate;
-};
-
-// for channels aka AudioTracks
-class SoundChannel : public SoundEvent {
-public:
-    enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
-    SoundChannel() : mState(IDLE), mNumChannels(1),
-            mPos(0), mToggle(0), mAutoPaused(false) {}
-    ~SoundChannel();
-    void init(SoundPool* soundPool);
-    void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
-            int priority, int loop, float rate);
-    void setVolume_l(float leftVolume, float rightVolume);
-    void setVolume(float leftVolume, float rightVolume);
-    void stop_l();
-    void stop();
-    void pause();
-    void autoPause();
-    void resume();
-    void autoResume();
-    void setRate(float rate);
-    int state() { return mState; }
-    void setPriority(int priority) { mPriority = priority; }
-    void setLoop(int loop);
-    int numChannels() { return mNumChannels; }
-    void clearNextEvent() { mNextEvent.clear(); }
-    void nextEvent();
-    int nextChannelID() { return mNextEvent.channelID(); }
-    void dump();
-
-private:
-    static void callback(int event, void* user, void *info);
-    void process(int event, void *info, unsigned long toggle);
-    bool doStop_l();
-
-    SoundPool*          mSoundPool;
-    sp<AudioTrack>      mAudioTrack;
-    SoundEvent          mNextEvent;
-    Mutex               mLock;
-    int                 mState;
-    int                 mNumChannels;
-    int                 mPos;
-    int                 mAudioBufferSize;
-    unsigned long       mToggle;
-    bool                mAutoPaused;
-};
-
-// application object for managing a pool of sounds
-class SoundPool {
-    friend class SoundPoolThread;
-    friend class SoundChannel;
-public:
-    SoundPool(int maxChannels, const audio_attributes_t* pAttributes);
-    ~SoundPool();
-    int load(const char* url, int priority);
-    int load(int fd, int64_t offset, int64_t length, int priority);
-    bool unload(int sampleID);
-    int play(int sampleID, float leftVolume, float rightVolume, int priority,
-            int loop, float rate);
-    void pause(int channelID);
-    void autoPause();
-    void resume(int channelID);
-    void autoResume();
-    void stop(int channelID);
-    void setVolume(int channelID, float leftVolume, float rightVolume);
-    void setPriority(int channelID, int priority);
-    void setLoop(int channelID, int loop);
-    void setRate(int channelID, float rate);
-    const audio_attributes_t* attributes() { return &mAttributes; }
-
-    // called from SoundPoolThread
-    void sampleLoaded(int sampleID);
-
-    // called from AudioTrack thread
-    void done_l(SoundChannel* channel);
-
-    // callback function
-    void setCallback(SoundPoolCallback* callback, void* user);
-    void* getUserData() { return mUserData; }
-
-private:
-    SoundPool() {} // no default constructor
-    bool startThreads();
-    void doLoad(sp<Sample>& sample);
-    sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
-    SoundChannel* findChannel (int channelID);
-    SoundChannel* findNextChannel (int channelID);
-    SoundChannel* allocateChannel_l(int priority);
-    void moveToFront_l(SoundChannel* channel);
-    void notify(SoundPoolEvent event);
-    void dump();
-
-    // restart thread
-    void addToRestartList(SoundChannel* channel);
-    void addToStopList(SoundChannel* channel);
-    static int beginThread(void* arg);
-    int run();
-    void quit();
-
-    Mutex                   mLock;
-    Mutex                   mRestartLock;
-    Condition               mCondition;
-    SoundPoolThread*        mDecodeThread;
-    SoundChannel*           mChannelPool;
-    List<SoundChannel*>     mChannels;
-    List<SoundChannel*>     mRestart;
-    List<SoundChannel*>     mStop;
-    DefaultKeyedVector< int, sp<Sample> >   mSamples;
-    int                     mMaxChannels;
-    audio_attributes_t      mAttributes;
-    int                     mAllocated;
-    int                     mNextSampleID;
-    int                     mNextChannelID;
-    bool                    mQuit;
-
-    // callback
-    Mutex                   mCallbackLock;
-    SoundPoolCallback*      mCallback;
-    void*                   mUserData;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOL_H_*/
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 9cc208e..5830933 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -232,17 +232,6 @@
             bool            isLooping();
             status_t        setVolume(float leftVolume, float rightVolume);
             void            notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
-    static  status_t        decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap,
-            size_t *pSize);
-    static  status_t        decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
-                                   int* pNumChannels, audio_format_t* pFormat,
-                                   const sp<IMemoryHeap>& heap, size_t *pSize);
             status_t        invoke(const Parcel& request, Parcel *reply);
             status_t        setMetadataFilter(const Parcel& filter);
             status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 371e2c8..595ace8 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -78,7 +78,7 @@
 
     static bool isFlexibleColorFormat(
             const sp<IOMX> &omx, IOMX::node_id node,
-            uint32_t colorFormat, OMX_U32 *flexibleEquivalent);
+            uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent);
 
     // Returns 0 if configuration is not supported.  NOTE: this is treated by
     // some OMX components as auto level, and by others as invalid level.
@@ -251,12 +251,13 @@
     status_t setVideoPortFormatType(
             OMX_U32 portIndex,
             OMX_VIDEO_CODINGTYPE compressionFormat,
-            OMX_COLOR_FORMATTYPE colorFormat);
+            OMX_COLOR_FORMATTYPE colorFormat,
+            bool usingNativeBuffers = false);
 
-    status_t setSupportedOutputFormat();
+    status_t setSupportedOutputFormat(bool getLegacyFlexibleFormat);
 
     status_t setupVideoDecoder(
-            const char *mime, const sp<AMessage> &msg);
+            const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers);
 
     status_t setupVideoEncoder(
             const char *mime, const sp<AMessage> &msg);
@@ -264,7 +265,7 @@
     status_t setVideoFormatOnPort(
             OMX_U32 portIndex,
             int32_t width, int32_t height,
-            OMX_VIDEO_CODINGTYPE compressionFormat);
+            OMX_VIDEO_CODINGTYPE compressionFormat, float frameRate = -1.0);
 
     typedef struct drcParams {
         int32_t drcCut;
diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h
index c3a68e1..822dbb3 100644
--- a/include/media/stagefright/foundation/AString.h
+++ b/include/media/stagefright/foundation/AString.h
@@ -102,7 +102,7 @@
     void makeMutable();
 };
 
-AString StringPrintf(const char *format, ...);
+AString AStringPrintf(const char *format, ...);
 
 }  // namespace android
 
diff --git a/media/libcpustats/ThreadCpuUsage.cpp b/media/libcpustats/ThreadCpuUsage.cpp
index 7b5b661..b43b36c 100644
--- a/media/libcpustats/ThreadCpuUsage.cpp
+++ b/media/libcpustats/ThreadCpuUsage.cpp
@@ -19,6 +19,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 #include <time.h>
 
 #include <utils/Log.h>
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 4215b89..5378bf2 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -58,8 +58,6 @@
     AudioEffect.cpp \
     Visualizer.cpp \
     MemoryLeakTrackUtil.cpp \
-    SoundPool.cpp \
-    SoundPoolThread.cpp \
     StringArray.cpp \
     AudioPolicy.cpp
 
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 7a18cba..f5a5712 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -590,18 +590,22 @@
 
 status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
                                                audio_policy_dev_state_t state,
-                                               const char *device_address)
+                                               const char *device_address,
+                                               const char *device_name)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     const char *address = "";
+    const char *name = "";
 
     if (aps == 0) return PERMISSION_DENIED;
 
     if (device_address != NULL) {
         address = device_address;
     }
-
-    return aps->setDeviceConnectionState(device, state, address);
+    if (device_name != NULL) {
+        name = device_name;
+    }
+    return aps->setDeviceConnectionState(device, state, address, name);
 }
 
 audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index dbc7a9e..b175055 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -84,13 +84,15 @@
     virtual status_t setDeviceConnectionState(
                                     audio_devices_t device,
                                     audio_policy_dev_state_t state,
-                                    const char *device_address)
+                                    const char *device_address,
+                                    const char *device_name)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(static_cast <uint32_t>(device));
         data.writeInt32(static_cast <uint32_t>(state));
         data.writeCString(device_address);
+        data.writeCString(device_name);
         remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
@@ -726,9 +728,11 @@
             audio_policy_dev_state_t state =
                     static_cast <audio_policy_dev_state_t>(data.readInt32());
             const char *device_address = data.readCString();
+            const char *device_name = data.readCString();
             reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
                                                                               state,
-                                                                              device_address)));
+                                                                              device_address,
+                                                                              device_name)));
             return NO_ERROR;
         } break;
 
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 4d33d40..feea267 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -39,8 +39,6 @@
 
 enum {
     CREATE = IBinder::FIRST_CALL_TRANSACTION,
-    DECODE_URL,
-    DECODE_FD,
     CREATE_MEDIA_RECORDER,
     CREATE_METADATA_RETRIEVER,
     GET_OMX,
@@ -88,59 +86,6 @@
         return interface_cast<IMediaRecorder>(reply.readStrongBinder());
     }
 
-    virtual status_t decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap,
-            size_t *pSize)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeInt32(httpService != NULL);
-        if (httpService != NULL) {
-            data.writeStrongBinder(IInterface::asBinder(httpService));
-        }
-        data.writeCString(url);
-        data.writeStrongBinder(IInterface::asBinder(heap));
-        status_t status = remote()->transact(DECODE_URL, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                *pSampleRate = uint32_t(reply.readInt32());
-                *pNumChannels = reply.readInt32();
-                *pFormat = (audio_format_t)reply.readInt32();
-                *pSize = (size_t)reply.readInt32();
-            }
-        }
-        return status;
-    }
-
-    virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
-                               int* pNumChannels, audio_format_t* pFormat,
-                               const sp<IMemoryHeap>& heap, size_t *pSize)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        data.writeFileDescriptor(fd);
-        data.writeInt64(offset);
-        data.writeInt64(length);
-        data.writeStrongBinder(IInterface::asBinder(heap));
-        status_t status = remote()->transact(DECODE_FD, data, &reply);
-        if (status == NO_ERROR) {
-            status = (status_t)reply.readInt32();
-            if (status == NO_ERROR) {
-                *pSampleRate = uint32_t(reply.readInt32());
-                *pNumChannels = reply.readInt32();
-                *pFormat = (audio_format_t)reply.readInt32();
-                *pSize = (size_t)reply.readInt32();
-            }
-        }
-        return status;
-    }
-
     virtual sp<IOMX> getOMX() {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -219,58 +164,6 @@
             reply->writeStrongBinder(IInterface::asBinder(player));
             return NO_ERROR;
         } break;
-        case DECODE_URL: {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            sp<IMediaHTTPService> httpService;
-            if (data.readInt32()) {
-                httpService =
-                    interface_cast<IMediaHTTPService>(data.readStrongBinder());
-            }
-            const char* url = data.readCString();
-            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
-            uint32_t sampleRate;
-            int numChannels;
-            audio_format_t format;
-            size_t size;
-            status_t status =
-                decode(httpService,
-                       url,
-                       &sampleRate,
-                       &numChannels,
-                       &format,
-                       heap,
-                       &size);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(sampleRate);
-                reply->writeInt32(numChannels);
-                reply->writeInt32((int32_t)format);
-                reply->writeInt32((int32_t)size);
-            }
-            return NO_ERROR;
-        } break;
-        case DECODE_FD: {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            int fd = dup(data.readFileDescriptor());
-            int64_t offset = data.readInt64();
-            int64_t length = data.readInt64();
-            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
-            uint32_t sampleRate;
-            int numChannels;
-            audio_format_t format;
-            size_t size;
-            status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format,
-                                     heap, &size);
-            ::close(fd);
-            reply->writeInt32(status);
-            if (status == NO_ERROR) {
-                reply->writeInt32(sampleRate);
-                reply->writeInt32(numChannels);
-                reply->writeInt32((int32_t)format);
-                reply->writeInt32((int32_t)size);
-            }
-            return NO_ERROR;
-        } break;
         case CREATE_MEDIA_RECORDER: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             sp<IMediaRecorder> recorder = createMediaRecorder();
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
index 66f7161..d31f721 100644
--- a/media/libmedia/MemoryLeakTrackUtil.cpp
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
 
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index 2181111..5197ce2 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -48,6 +48,8 @@
 }
 
 MidiIoWrapper::MidiIoWrapper(const sp<DataSource> &source) {
+    ALOGV("MidiIoWrapper(DataSource)");
+    mFd = -1;
     mDataSource = source;
     off64_t l;
     if (mDataSource->getSize(&l) == OK) {
@@ -76,7 +78,7 @@
 }
 
 int MidiIoWrapper::size() {
-    ALOGV("size() = %d", mLength);
+    ALOGV("size() = %d", int(mLength));
     return mLength;
 }
 
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
deleted file mode 100644
index 76f11dc..0000000
--- a/media/libmedia/SoundPool.cpp
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SoundPool"
-
-#include <inttypes.h>
-
-#include <utils/Log.h>
-
-#define USE_SHARED_MEM_BUFFER
-
-#include <media/AudioTrack.h>
-#include <media/IMediaHTTPService.h>
-#include <media/mediaplayer.h>
-#include <media/SoundPool.h>
-#include "SoundPoolThread.h"
-#include <media/AudioPolicyHelper.h>
-
-namespace android
-{
-
-int kDefaultBufferCount = 4;
-uint32_t kMaxSampleRate = 48000;
-uint32_t kDefaultSampleRate = 44100;
-uint32_t kDefaultFrameCount = 1200;
-size_t kDefaultHeapSize = 1024 * 1024; // 1MB
-
-
-SoundPool::SoundPool(int maxChannels, const audio_attributes_t* pAttributes)
-{
-    ALOGV("SoundPool constructor: maxChannels=%d, attr.usage=%d, attr.flags=0x%x, attr.tags=%s",
-            maxChannels, pAttributes->usage, pAttributes->flags, pAttributes->tags);
-
-    // check limits
-    mMaxChannels = maxChannels;
-    if (mMaxChannels < 1) {
-        mMaxChannels = 1;
-    }
-    else if (mMaxChannels > 32) {
-        mMaxChannels = 32;
-    }
-    ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
-
-    mQuit = false;
-    mDecodeThread = 0;
-    memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
-    mAllocated = 0;
-    mNextSampleID = 0;
-    mNextChannelID = 0;
-
-    mCallback = 0;
-    mUserData = 0;
-
-    mChannelPool = new SoundChannel[mMaxChannels];
-    for (int i = 0; i < mMaxChannels; ++i) {
-        mChannelPool[i].init(this);
-        mChannels.push_back(&mChannelPool[i]);
-    }
-
-    // start decode thread
-    startThreads();
-}
-
-SoundPool::~SoundPool()
-{
-    ALOGV("SoundPool destructor");
-    mDecodeThread->quit();
-    quit();
-
-    Mutex::Autolock lock(&mLock);
-
-    mChannels.clear();
-    if (mChannelPool)
-        delete [] mChannelPool;
-    // clean up samples
-    ALOGV("clear samples");
-    mSamples.clear();
-
-    if (mDecodeThread)
-        delete mDecodeThread;
-}
-
-void SoundPool::addToRestartList(SoundChannel* channel)
-{
-    Mutex::Autolock lock(&mRestartLock);
-    if (!mQuit) {
-        mRestart.push_back(channel);
-        mCondition.signal();
-    }
-}
-
-void SoundPool::addToStopList(SoundChannel* channel)
-{
-    Mutex::Autolock lock(&mRestartLock);
-    if (!mQuit) {
-        mStop.push_back(channel);
-        mCondition.signal();
-    }
-}
-
-int SoundPool::beginThread(void* arg)
-{
-    SoundPool* p = (SoundPool*)arg;
-    return p->run();
-}
-
-int SoundPool::run()
-{
-    mRestartLock.lock();
-    while (!mQuit) {
-        mCondition.wait(mRestartLock);
-        ALOGV("awake");
-        if (mQuit) break;
-
-        while (!mStop.empty()) {
-            SoundChannel* channel;
-            ALOGV("Getting channel from stop list");
-            List<SoundChannel* >::iterator iter = mStop.begin();
-            channel = *iter;
-            mStop.erase(iter);
-            mRestartLock.unlock();
-            if (channel != 0) {
-                Mutex::Autolock lock(&mLock);
-                channel->stop();
-            }
-            mRestartLock.lock();
-            if (mQuit) break;
-        }
-
-        while (!mRestart.empty()) {
-            SoundChannel* channel;
-            ALOGV("Getting channel from list");
-            List<SoundChannel*>::iterator iter = mRestart.begin();
-            channel = *iter;
-            mRestart.erase(iter);
-            mRestartLock.unlock();
-            if (channel != 0) {
-                Mutex::Autolock lock(&mLock);
-                channel->nextEvent();
-            }
-            mRestartLock.lock();
-            if (mQuit) break;
-        }
-    }
-
-    mStop.clear();
-    mRestart.clear();
-    mCondition.signal();
-    mRestartLock.unlock();
-    ALOGV("goodbye");
-    return 0;
-}
-
-void SoundPool::quit()
-{
-    mRestartLock.lock();
-    mQuit = true;
-    mCondition.signal();
-    mCondition.wait(mRestartLock);
-    ALOGV("return from quit");
-    mRestartLock.unlock();
-}
-
-bool SoundPool::startThreads()
-{
-    createThreadEtc(beginThread, this, "SoundPool");
-    if (mDecodeThread == NULL)
-        mDecodeThread = new SoundPoolThread(this);
-    return mDecodeThread != NULL;
-}
-
-SoundChannel* SoundPool::findChannel(int channelID)
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        if (mChannelPool[i].channelID() == channelID) {
-            return &mChannelPool[i];
-        }
-    }
-    return NULL;
-}
-
-SoundChannel* SoundPool::findNextChannel(int channelID)
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        if (mChannelPool[i].nextChannelID() == channelID) {
-            return &mChannelPool[i];
-        }
-    }
-    return NULL;
-}
-
-int SoundPool::load(const char* path, int priority __unused)
-{
-    ALOGV("load: path=%s, priority=%d", path, priority);
-    Mutex::Autolock lock(&mLock);
-    sp<Sample> sample = new Sample(++mNextSampleID, path);
-    mSamples.add(sample->sampleID(), sample);
-    doLoad(sample);
-    return sample->sampleID();
-}
-
-int SoundPool::load(int fd, int64_t offset, int64_t length, int priority __unused)
-{
-    ALOGV("load: fd=%d, offset=%" PRId64 ", length=%" PRId64 ", priority=%d",
-            fd, offset, length, priority);
-    Mutex::Autolock lock(&mLock);
-    sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
-    mSamples.add(sample->sampleID(), sample);
-    doLoad(sample);
-    return sample->sampleID();
-}
-
-void SoundPool::doLoad(sp<Sample>& sample)
-{
-    ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
-    sample->startLoad();
-    mDecodeThread->loadSample(sample->sampleID());
-}
-
-bool SoundPool::unload(int sampleID)
-{
-    ALOGV("unload: sampleID=%d", sampleID);
-    Mutex::Autolock lock(&mLock);
-    return mSamples.removeItem(sampleID);
-}
-
-int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
-        int priority, int loop, float rate)
-{
-    ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
-            sampleID, leftVolume, rightVolume, priority, loop, rate);
-    sp<Sample> sample;
-    SoundChannel* channel;
-    int channelID;
-
-    Mutex::Autolock lock(&mLock);
-
-    if (mQuit) {
-        return 0;
-    }
-    // is sample ready?
-    sample = findSample(sampleID);
-    if ((sample == 0) || (sample->state() != Sample::READY)) {
-        ALOGW("  sample %d not READY", sampleID);
-        return 0;
-    }
-
-    dump();
-
-    // allocate a channel
-    channel = allocateChannel_l(priority);
-
-    // no channel allocated - return 0
-    if (!channel) {
-        ALOGV("No channel allocated");
-        return 0;
-    }
-
-    channelID = ++mNextChannelID;
-
-    ALOGV("play channel %p state = %d", channel, channel->state());
-    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
-    return channelID;
-}
-
-SoundChannel* SoundPool::allocateChannel_l(int priority)
-{
-    List<SoundChannel*>::iterator iter;
-    SoundChannel* channel = NULL;
-
-    // allocate a channel
-    if (!mChannels.empty()) {
-        iter = mChannels.begin();
-        if (priority >= (*iter)->priority()) {
-            channel = *iter;
-            mChannels.erase(iter);
-            ALOGV("Allocated active channel");
-        }
-    }
-
-    // update priority and put it back in the list
-    if (channel) {
-        channel->setPriority(priority);
-        for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-            if (priority < (*iter)->priority()) {
-                break;
-            }
-        }
-        mChannels.insert(iter, channel);
-    }
-    return channel;
-}
-
-// move a channel from its current position to the front of the list
-void SoundPool::moveToFront_l(SoundChannel* channel)
-{
-    for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
-        if (*iter == channel) {
-            mChannels.erase(iter);
-            mChannels.push_front(channel);
-            break;
-        }
-    }
-}
-
-void SoundPool::pause(int channelID)
-{
-    ALOGV("pause(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->pause();
-    }
-}
-
-void SoundPool::autoPause()
-{
-    ALOGV("autoPause()");
-    Mutex::Autolock lock(&mLock);
-    for (int i = 0; i < mMaxChannels; ++i) {
-        SoundChannel* channel = &mChannelPool[i];
-        channel->autoPause();
-    }
-}
-
-void SoundPool::resume(int channelID)
-{
-    ALOGV("resume(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->resume();
-    }
-}
-
-void SoundPool::autoResume()
-{
-    ALOGV("autoResume()");
-    Mutex::Autolock lock(&mLock);
-    for (int i = 0; i < mMaxChannels; ++i) {
-        SoundChannel* channel = &mChannelPool[i];
-        channel->autoResume();
-    }
-}
-
-void SoundPool::stop(int channelID)
-{
-    ALOGV("stop(%d)", channelID);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->stop();
-    } else {
-        channel = findNextChannel(channelID);
-        if (channel)
-            channel->clearNextEvent();
-    }
-}
-
-void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
-{
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setVolume(leftVolume, rightVolume);
-    }
-}
-
-void SoundPool::setPriority(int channelID, int priority)
-{
-    ALOGV("setPriority(%d, %d)", channelID, priority);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setPriority(priority);
-    }
-}
-
-void SoundPool::setLoop(int channelID, int loop)
-{
-    ALOGV("setLoop(%d, %d)", channelID, loop);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setLoop(loop);
-    }
-}
-
-void SoundPool::setRate(int channelID, float rate)
-{
-    ALOGV("setRate(%d, %f)", channelID, rate);
-    Mutex::Autolock lock(&mLock);
-    SoundChannel* channel = findChannel(channelID);
-    if (channel) {
-        channel->setRate(rate);
-    }
-}
-
-// call with lock held
-void SoundPool::done_l(SoundChannel* channel)
-{
-    ALOGV("done_l(%d)", channel->channelID());
-    // if "stolen", play next event
-    if (channel->nextChannelID() != 0) {
-        ALOGV("add to restart list");
-        addToRestartList(channel);
-    }
-
-    // return to idle state
-    else {
-        ALOGV("move to front");
-        moveToFront_l(channel);
-    }
-}
-
-void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
-{
-    Mutex::Autolock lock(&mCallbackLock);
-    mCallback = callback;
-    mUserData = user;
-}
-
-void SoundPool::notify(SoundPoolEvent event)
-{
-    Mutex::Autolock lock(&mCallbackLock);
-    if (mCallback != NULL) {
-        mCallback(event, this, mUserData);
-    }
-}
-
-void SoundPool::dump()
-{
-    for (int i = 0; i < mMaxChannels; ++i) {
-        mChannelPool[i].dump();
-    }
-}
-
-
-Sample::Sample(int sampleID, const char* url)
-{
-    init();
-    mSampleID = sampleID;
-    mUrl = strdup(url);
-    ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl);
-}
-
-Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
-{
-    init();
-    mSampleID = sampleID;
-    mFd = dup(fd);
-    mOffset = offset;
-    mLength = length;
-    ALOGV("create sampleID=%d, fd=%d, offset=%" PRId64 " length=%" PRId64,
-        mSampleID, mFd, mLength, mOffset);
-}
-
-void Sample::init()
-{
-    mSize = 0;
-    mRefCount = 0;
-    mSampleID = 0;
-    mState = UNLOADED;
-    mFd = -1;
-    mOffset = 0;
-    mLength = 0;
-    mUrl = 0;
-}
-
-Sample::~Sample()
-{
-    ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
-    if (mFd > 0) {
-        ALOGV("close(%d)", mFd);
-        ::close(mFd);
-    }
-    free(mUrl);
-}
-
-status_t Sample::doLoad()
-{
-    uint32_t sampleRate;
-    int numChannels;
-    audio_format_t format;
-    status_t status;
-    mHeap = new MemoryHeapBase(kDefaultHeapSize);
-
-    ALOGV("Start decode");
-    if (mUrl) {
-        status = MediaPlayer::decode(
-                NULL /* httpService */,
-                mUrl,
-                &sampleRate,
-                &numChannels,
-                &format,
-                mHeap,
-                &mSize);
-    } else {
-        status = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format,
-                                     mHeap, &mSize);
-        ALOGV("close(%d)", mFd);
-        ::close(mFd);
-        mFd = -1;
-    }
-    if (status != NO_ERROR) {
-        ALOGE("Unable to load sample: %s", mUrl);
-        goto error;
-    }
-    ALOGV("pointer = %p, size = %zu, sampleRate = %u, numChannels = %d",
-          mHeap->getBase(), mSize, sampleRate, numChannels);
-
-    if (sampleRate > kMaxSampleRate) {
-       ALOGE("Sample rate (%u) out of range", sampleRate);
-       status = BAD_VALUE;
-       goto error;
-    }
-
-    if ((numChannels < 1) || (numChannels > 2)) {
-        ALOGE("Sample channel count (%d) out of range", numChannels);
-        status = BAD_VALUE;
-        goto error;
-    }
-
-    mData = new MemoryBase(mHeap, 0, mSize);
-    mSampleRate = sampleRate;
-    mNumChannels = numChannels;
-    mFormat = format;
-    mState = READY;
-    return NO_ERROR;
-
-error:
-    mHeap.clear();
-    return status;
-}
-
-
-void SoundChannel::init(SoundPool* soundPool)
-{
-    mSoundPool = soundPool;
-}
-
-// call with sound pool lock held
-void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
-        float rightVolume, int priority, int loop, float rate)
-{
-    sp<AudioTrack> oldTrack;
-    sp<AudioTrack> newTrack;
-    status_t status;
-
-    { // scope for the lock
-        Mutex::Autolock lock(&mLock);
-
-        ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
-                " priority=%d, loop=%d, rate=%f",
-                this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
-                priority, loop, rate);
-
-        // if not idle, this voice is being stolen
-        if (mState != IDLE) {
-            ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
-            mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-            stop_l();
-            return;
-        }
-
-        // initialize track
-        size_t afFrameCount;
-        uint32_t afSampleRate;
-        audio_stream_type_t streamType = audio_attributes_to_stream_type(mSoundPool->attributes());
-        if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
-            afFrameCount = kDefaultFrameCount;
-        }
-        if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
-            afSampleRate = kDefaultSampleRate;
-        }
-        int numChannels = sample->numChannels();
-        uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
-        uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
-        uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
-        size_t frameCount = 0;
-
-        if (loop) {
-            frameCount = sample->size()/numChannels/
-                ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
-        }
-
-#ifndef USE_SHARED_MEM_BUFFER
-        // Ensure minimum audio buffer size in case of short looped sample
-        if(frameCount < totalFrames) {
-            frameCount = totalFrames;
-        }
-#endif
-
-        // mToggle toggles each time a track is started on a given channel.
-        // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
-        // as callback user data. This enables the detection of callbacks received from the old
-        // audio track while the new one is being started and avoids processing them with
-        // wrong audio audio buffer size  (mAudioBufferSize)
-        unsigned long toggle = mToggle ^ 1;
-        void *userData = (void *)((unsigned long)this | toggle);
-        audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
-
-        // do not create a new audio track if current track is compatible with sample parameters
-#ifdef USE_SHARED_MEM_BUFFER
-        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
-#else
-        newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
-                bufferFrames);
-#endif
-        oldTrack = mAudioTrack;
-        status = newTrack->initCheck();
-        if (status != NO_ERROR) {
-            ALOGE("Error creating AudioTrack");
-            goto exit;
-        }
-        ALOGV("setVolume %p", newTrack.get());
-        newTrack->setVolume(leftVolume, rightVolume);
-        newTrack->setLoop(0, frameCount, loop);
-
-        // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
-        mToggle = toggle;
-        mAudioTrack = newTrack;
-        mPos = 0;
-        mSample = sample;
-        mChannelID = nextChannelID;
-        mPriority = priority;
-        mLoop = loop;
-        mLeftVolume = leftVolume;
-        mRightVolume = rightVolume;
-        mNumChannels = numChannels;
-        mRate = rate;
-        clearNextEvent();
-        mState = PLAYING;
-        mAudioTrack->start();
-        mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
-    }
-
-exit:
-    ALOGV("delete oldTrack %p", oldTrack.get());
-    if (status != NO_ERROR) {
-        mAudioTrack.clear();
-    }
-}
-
-void SoundChannel::nextEvent()
-{
-    sp<Sample> sample;
-    int nextChannelID;
-    float leftVolume;
-    float rightVolume;
-    int priority;
-    int loop;
-    float rate;
-
-    // check for valid event
-    {
-        Mutex::Autolock lock(&mLock);
-        nextChannelID = mNextEvent.channelID();
-        if (nextChannelID  == 0) {
-            ALOGV("stolen channel has no event");
-            return;
-        }
-
-        sample = mNextEvent.sample();
-        leftVolume = mNextEvent.leftVolume();
-        rightVolume = mNextEvent.rightVolume();
-        priority = mNextEvent.priority();
-        loop = mNextEvent.loop();
-        rate = mNextEvent.rate();
-    }
-
-    ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
-    play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
-}
-
-void SoundChannel::callback(int event, void* user, void *info)
-{
-    SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
-
-    channel->process(event, info, (unsigned long)user & 1);
-}
-
-void SoundChannel::process(int event, void *info, unsigned long toggle)
-{
-    //ALOGV("process(%d)", mChannelID);
-
-    Mutex::Autolock lock(&mLock);
-
-    AudioTrack::Buffer* b = NULL;
-    if (event == AudioTrack::EVENT_MORE_DATA) {
-       b = static_cast<AudioTrack::Buffer *>(info);
-    }
-
-    if (mToggle != toggle) {
-        ALOGV("process wrong toggle %p channel %d", this, mChannelID);
-        if (b != NULL) {
-            b->size = 0;
-        }
-        return;
-    }
-
-    sp<Sample> sample = mSample;
-
-//    ALOGV("SoundChannel::process event %d", event);
-
-    if (event == AudioTrack::EVENT_MORE_DATA) {
-
-        // check for stop state
-        if (b->size == 0) return;
-
-        if (mState == IDLE) {
-            b->size = 0;
-            return;
-        }
-
-        if (sample != 0) {
-            // fill buffer
-            uint8_t* q = (uint8_t*) b->i8;
-            size_t count = 0;
-
-            if (mPos < (int)sample->size()) {
-                uint8_t* p = sample->data() + mPos;
-                count = sample->size() - mPos;
-                if (count > b->size) {
-                    count = b->size;
-                }
-                memcpy(q, p, count);
-//              ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size,
-//                      count);
-            } else if (mPos < mAudioBufferSize) {
-                count = mAudioBufferSize - mPos;
-                if (count > b->size) {
-                    count = b->size;
-                }
-                memset(q, 0, count);
-//              ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
-            }
-
-            mPos += count;
-            b->size = count;
-            //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
-        }
-    } else if (event == AudioTrack::EVENT_UNDERRUN || event == AudioTrack::EVENT_BUFFER_END) {
-        ALOGV("process %p channel %d event %s",
-              this, mChannelID, (event == AudioTrack::EVENT_UNDERRUN) ? "UNDERRUN" :
-                      "BUFFER_END");
-        mSoundPool->addToStopList(this);
-    } else if (event == AudioTrack::EVENT_LOOP_END) {
-        ALOGV("End loop %p channel %d", this, mChannelID);
-    } else if (event == AudioTrack::EVENT_NEW_IAUDIOTRACK) {
-        ALOGV("process %p channel %d NEW_IAUDIOTRACK", this, mChannelID);
-    } else {
-        ALOGW("SoundChannel::process unexpected event %d", event);
-    }
-}
-
-
-// call with lock held
-bool SoundChannel::doStop_l()
-{
-    if (mState != IDLE) {
-        setVolume_l(0, 0);
-        ALOGV("stop");
-        mAudioTrack->stop();
-        mSample.clear();
-        mState = IDLE;
-        mPriority = IDLE_PRIORITY;
-        return true;
-    }
-    return false;
-}
-
-// call with lock held and sound pool lock held
-void SoundChannel::stop_l()
-{
-    if (doStop_l()) {
-        mSoundPool->done_l(this);
-    }
-}
-
-// call with sound pool lock held
-void SoundChannel::stop()
-{
-    bool stopped;
-    {
-        Mutex::Autolock lock(&mLock);
-        stopped = doStop_l();
-    }
-
-    if (stopped) {
-        mSoundPool->done_l(this);
-    }
-}
-
-//FIXME: Pause is a little broken right now
-void SoundChannel::pause()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PLAYING) {
-        ALOGV("pause track");
-        mState = PAUSED;
-        mAudioTrack->pause();
-    }
-}
-
-void SoundChannel::autoPause()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PLAYING) {
-        ALOGV("pause track");
-        mState = PAUSED;
-        mAutoPaused = true;
-        mAudioTrack->pause();
-    }
-}
-
-void SoundChannel::resume()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mState == PAUSED) {
-        ALOGV("resume track");
-        mState = PLAYING;
-        mAutoPaused = false;
-        mAudioTrack->start();
-    }
-}
-
-void SoundChannel::autoResume()
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAutoPaused && (mState == PAUSED)) {
-        ALOGV("resume track");
-        mState = PLAYING;
-        mAutoPaused = false;
-        mAudioTrack->start();
-    }
-}
-
-void SoundChannel::setRate(float rate)
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAudioTrack != NULL && mSample != 0) {
-        uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
-        mAudioTrack->setSampleRate(sampleRate);
-        mRate = rate;
-    }
-}
-
-// call with lock held
-void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
-{
-    mLeftVolume = leftVolume;
-    mRightVolume = rightVolume;
-    if (mAudioTrack != NULL)
-        mAudioTrack->setVolume(leftVolume, rightVolume);
-}
-
-void SoundChannel::setVolume(float leftVolume, float rightVolume)
-{
-    Mutex::Autolock lock(&mLock);
-    setVolume_l(leftVolume, rightVolume);
-}
-
-void SoundChannel::setLoop(int loop)
-{
-    Mutex::Autolock lock(&mLock);
-    if (mAudioTrack != NULL && mSample != 0) {
-        uint32_t loopEnd = mSample->size()/mNumChannels/
-            ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
-        mAudioTrack->setLoop(0, loopEnd, loop);
-        mLoop = loop;
-    }
-}
-
-SoundChannel::~SoundChannel()
-{
-    ALOGV("SoundChannel destructor %p", this);
-    {
-        Mutex::Autolock lock(&mLock);
-        clearNextEvent();
-        doStop_l();
-    }
-    // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
-    // callback thread to exit which may need to execute process() and acquire the mLock.
-    mAudioTrack.clear();
-}
-
-void SoundChannel::dump()
-{
-    ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
-            mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
-}
-
-void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
-            float rightVolume, int priority, int loop, float rate)
-{
-    mSample = sample;
-    mChannelID = channelID;
-    mLeftVolume = leftVolume;
-    mRightVolume = rightVolume;
-    mPriority = priority;
-    mLoop = loop;
-    mRate =rate;
-}
-
-} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.cpp b/media/libmedia/SoundPoolThread.cpp
deleted file mode 100644
index ba3b482..0000000
--- a/media/libmedia/SoundPoolThread.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SoundPoolThread"
-#include "utils/Log.h"
-
-#include "SoundPoolThread.h"
-
-namespace android {
-
-void SoundPoolThread::write(SoundPoolMsg msg) {
-    Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() >= maxMessages) {
-        mCondition.wait(mLock);
-    }
-
-    // if thread is quitting, don't add to queue
-    if (mRunning) {
-        mMsgQueue.push(msg);
-        mCondition.signal();
-    }
-}
-
-const SoundPoolMsg SoundPoolThread::read() {
-    Mutex::Autolock lock(&mLock);
-    while (mMsgQueue.size() == 0) {
-        mCondition.wait(mLock);
-    }
-    SoundPoolMsg msg = mMsgQueue[0];
-    mMsgQueue.removeAt(0);
-    mCondition.signal();
-    return msg;
-}
-
-void SoundPoolThread::quit() {
-    Mutex::Autolock lock(&mLock);
-    if (mRunning) {
-        mRunning = false;
-        mMsgQueue.clear();
-        mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
-        mCondition.signal();
-        mCondition.wait(mLock);
-    }
-    ALOGV("return from quit");
-}
-
-SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
-    mSoundPool(soundPool)
-{
-    mMsgQueue.setCapacity(maxMessages);
-    if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
-        mRunning = true;
-    }
-}
-
-SoundPoolThread::~SoundPoolThread()
-{
-    quit();
-}
-
-int SoundPoolThread::beginThread(void* arg) {
-    ALOGV("beginThread");
-    SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
-    return soundPoolThread->run();
-}
-
-int SoundPoolThread::run() {
-    ALOGV("run");
-    for (;;) {
-        SoundPoolMsg msg = read();
-        ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
-        switch (msg.mMessageType) {
-        case SoundPoolMsg::KILL:
-            ALOGV("goodbye");
-            return NO_ERROR;
-        case SoundPoolMsg::LOAD_SAMPLE:
-            doLoadSample(msg.mData);
-            break;
-        default:
-            ALOGW("run: Unrecognized message %d\n",
-                    msg.mMessageType);
-            break;
-        }
-    }
-}
-
-void SoundPoolThread::loadSample(int sampleID) {
-    write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
-}
-
-void SoundPoolThread::doLoadSample(int sampleID) {
-    sp <Sample> sample = mSoundPool->findSample(sampleID);
-    status_t status = -1;
-    if (sample != 0) {
-        status = sample->doLoad();
-    }
-    mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
-}
-
-} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.h b/media/libmedia/SoundPoolThread.h
deleted file mode 100644
index 7e96900..0000000
--- a/media/libmedia/SoundPoolThread.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef SOUNDPOOLTHREAD_H_
-#define SOUNDPOOLTHREAD_H_
-
-#include <utils/threads.h>
-#include <utils/Vector.h>
-#include <media/AudioTrack.h>
-
-#include <media/SoundPool.h>
-
-namespace android {
-
-class SoundPoolMsg {
-public:
-    enum MessageType { INVALID, KILL, LOAD_SAMPLE };
-    SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
-    SoundPoolMsg(MessageType MessageType, int data) :
-        mMessageType(MessageType), mData(data) {}
-    uint16_t         mMessageType;
-    uint16_t         mData;
-};
-
-/*
- * This class handles background requests from the SoundPool
- */
-class SoundPoolThread {
-public:
-    SoundPoolThread(SoundPool* SoundPool);
-    ~SoundPoolThread();
-    void loadSample(int sampleID);
-    void quit();
-    void write(SoundPoolMsg msg);
-
-private:
-    static const size_t maxMessages = 5;
-
-    static int beginThread(void* arg);
-    int run();
-    void doLoadSample(int sampleID);
-    const SoundPoolMsg read();
-
-    Mutex                   mLock;
-    Condition               mCondition;
-    Vector<SoundPoolMsg>    mMsgQueue;
-    SoundPool*              mSoundPool;
-    bool                    mRunning;
-};
-
-} // end namespace android
-
-#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 9bfd813..432ecda 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -838,53 +838,12 @@
     }
 }
 
-/*static*/ status_t MediaPlayer::decode(
-        const sp<IMediaHTTPService> &httpService,
-        const char* url,
-        uint32_t *pSampleRate,
-        int* pNumChannels,
-        audio_format_t* pFormat,
-        const sp<IMemoryHeap>& heap,
-        size_t *pSize)
-{
-    ALOGV("decode(%s)", url);
-    status_t status;
-    const sp<IMediaPlayerService>& service = getMediaPlayerService();
-    if (service != 0) {
-        status = service->decode(httpService, url, pSampleRate, pNumChannels, pFormat, heap, pSize);
-    } else {
-        ALOGE("Unable to locate media service");
-        status = DEAD_OBJECT;
-    }
-    return status;
-
-}
-
 void MediaPlayer::died()
 {
     ALOGV("died");
     notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
 }
 
-/*static*/ status_t MediaPlayer::decode(int fd, int64_t offset, int64_t length,
-                                        uint32_t *pSampleRate, int* pNumChannels,
-                                        audio_format_t* pFormat,
-                                        const sp<IMemoryHeap>& heap, size_t *pSize)
-{
-    ALOGV("decode(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
-    status_t status;
-    const sp<IMediaPlayerService>& service = getMediaPlayerService();
-    if (service != 0) {
-        status = service->decode(fd, offset, length, pSampleRate,
-                                 pNumChannels, pFormat, heap, pSize);
-    } else {
-        ALOGE("Unable to locate media service");
-        status = DEAD_OBJECT;
-    }
-    return status;
-
-}
-
 status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
     if (mPlayer == NULL) {
         return NO_INIT;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index cf6771e..1936218 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -384,28 +384,6 @@
     return new RemoteDisplay(client, iface.string());
 }
 
-status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& /*args*/) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    result.append(" AudioCache\n");
-    if (mHeap != 0) {
-        snprintf(buffer, 255, "  heap base(%p), size(%zu), flags(%d)\n",
-                mHeap->getBase(), mHeap->getSize(), mHeap->getFlags());
-        result.append(buffer);
-    }
-    snprintf(buffer, 255, "  msec per frame(%f), channel count(%d), format(%d), frame count(%zd)\n",
-            mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
-    result.append(buffer);
-    snprintf(buffer, 255, "  sample rate(%d), size(%d), error(%d), command complete(%s)\n",
-            mSampleRate, mSize, mError, mCommandComplete?"true":"false");
-    result.append(buffer);
-    ::write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
 status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
 {
     const size_t SIZE = 256;
@@ -1279,128 +1257,6 @@
 }
 #endif
 
-status_t MediaPlayerService::decode(
-        const sp<IMediaHTTPService> &httpService,
-        const char* url,
-        uint32_t *pSampleRate,
-        int* pNumChannels,
-        audio_format_t* pFormat,
-        const sp<IMemoryHeap>& heap,
-        size_t *pSize)
-{
-    ALOGV("decode(%s)", url);
-    sp<MediaPlayerBase> player;
-    status_t status = BAD_VALUE;
-
-    // Protect our precious, precious DRMd ringtones by only allowing
-    // decoding of http, but not filesystem paths or content Uris.
-    // If the application wants to decode those, it should open a
-    // filedescriptor for them and use that.
-    if (url != NULL && strncmp(url, "http://", 7) != 0) {
-        ALOGD("Can't decode %s by path, use filedescriptor instead", url);
-        return BAD_VALUE;
-    }
-
-    player_type playerType =
-        MediaPlayerFactory::getPlayerType(NULL /* client */, url);
-    ALOGV("player type = %d", playerType);
-
-    // create the right type of player
-    sp<AudioCache> cache = new AudioCache(heap);
-    player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
-    if (player == NULL) goto Exit;
-    if (player->hardwareOutput()) goto Exit;
-
-    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
-
-    // set data source
-    if (player->setDataSource(httpService, url) != NO_ERROR) goto Exit;
-
-    ALOGV("prepare");
-    player->prepareAsync();
-
-    ALOGV("wait for prepare");
-    if (cache->wait() != NO_ERROR) goto Exit;
-
-    ALOGV("start");
-    player->start();
-
-    ALOGV("wait for playback complete");
-    cache->wait();
-    // in case of error, return what was successfully decoded.
-    if (cache->size() == 0) {
-        goto Exit;
-    }
-
-    *pSize = cache->size();
-    *pSampleRate = cache->sampleRate();
-    *pNumChannels = cache->channelCount();
-    *pFormat = cache->format();
-    ALOGV("return size %d sampleRate=%u, channelCount = %d, format = %d",
-          *pSize, *pSampleRate, *pNumChannels, *pFormat);
-    status = NO_ERROR;
-
-Exit:
-    if (player != 0) player->reset();
-    return status;
-}
-
-status_t MediaPlayerService::decode(int fd, int64_t offset, int64_t length,
-                                       uint32_t *pSampleRate, int* pNumChannels,
-                                       audio_format_t* pFormat,
-                                       const sp<IMemoryHeap>& heap, size_t *pSize)
-{
-    ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
-    sp<MediaPlayerBase> player;
-    status_t status = BAD_VALUE;
-
-    player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */,
-                                                               fd,
-                                                               offset,
-                                                               length);
-    ALOGV("player type = %d", playerType);
-
-    // create the right type of player
-    sp<AudioCache> cache = new AudioCache(heap);
-    player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
-    if (player == NULL) goto Exit;
-    if (player->hardwareOutput()) goto Exit;
-
-    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
-
-    // set data source
-    if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
-
-    ALOGV("prepare");
-    player->prepareAsync();
-
-    ALOGV("wait for prepare");
-    if (cache->wait() != NO_ERROR) goto Exit;
-
-    ALOGV("start");
-    player->start();
-
-    ALOGV("wait for playback complete");
-    cache->wait();
-    // in case of error, return what was successfully decoded.
-    if (cache->size() == 0) {
-        goto Exit;
-    }
-
-    *pSize = cache->size();
-    *pSampleRate = cache->sampleRate();
-    *pNumChannels = cache->channelCount();
-    *pFormat = cache->format();
-    ALOGV("return size %d, sampleRate=%u, channelCount = %d, format = %d",
-          *pSize, *pSampleRate, *pNumChannels, *pFormat);
-    status = NO_ERROR;
-
-Exit:
-    if (player != 0) player->reset();
-    return status;
-}
-
-
 #undef LOG_TAG
 #define LOG_TAG "AudioSink"
 MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid,
@@ -1950,47 +1806,6 @@
     return mTrack->getSampleRate();
 }
 
-#undef LOG_TAG
-#define LOG_TAG "AudioCache"
-MediaPlayerService::AudioCache::AudioCache(const sp<IMemoryHeap>& heap) :
-    mHeap(heap), mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
-    mFrameSize(1), mError(NO_ERROR),  mCommandComplete(false)
-{
-}
-
-uint32_t MediaPlayerService::AudioCache::latency () const
-{
-    return 0;
-}
-
-float MediaPlayerService::AudioCache::msecsPerFrame() const
-{
-    return mMsecsPerFrame;
-}
-
-status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position) const
-{
-    if (position == 0) return BAD_VALUE;
-    *position = mSize / mFrameSize;
-    return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::getTimestamp(AudioTimestamp &ts) const
-{
-    ts.mPosition = mSize / mFrameSize;
-    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    ts.mTime.tv_sec = now / 1000000000LL;
-    ts.mTime.tv_nsec = now - (1000000000LL * ts.mTime.tv_sec);
-    return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::getFramesWritten(uint32_t *written) const
-{
-    if (written == 0) return BAD_VALUE;
-    *written = mSize / mFrameSize;
-    return NO_ERROR;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 
 struct CallbackThread : public Thread {
@@ -2058,139 +1873,6 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-status_t MediaPlayerService::AudioCache::open(
-        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-        audio_format_t format, int bufferCount,
-        AudioCallback cb, void *cookie, audio_output_flags_t /*flags*/,
-        const audio_offload_info_t* /*offloadInfo*/)
-{
-    ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
-    if (mHeap->getHeapID() < 0) {
-        return NO_INIT;
-    }
-
-    mSampleRate = sampleRate;
-    mChannelCount = (uint16_t)channelCount;
-    mFormat = format;
-    mMsecsPerFrame = 1.e3 / (float) sampleRate;
-    mFrameSize =  audio_is_linear_pcm(mFormat)
-            ? mChannelCount * audio_bytes_per_sample(mFormat) : 1;
-    mFrameCount = mHeap->getSize() / mFrameSize;
-
-    if (cb != NULL) {
-        mCallbackThread = new CallbackThread(this, cb, cookie);
-    }
-    return NO_ERROR;
-}
-
-status_t MediaPlayerService::AudioCache::start() {
-    if (mCallbackThread != NULL) {
-        mCallbackThread->run("AudioCache callback");
-    }
-    return NO_ERROR;
-}
-
-void MediaPlayerService::AudioCache::stop() {
-    if (mCallbackThread != NULL) {
-        mCallbackThread->requestExitAndWait();
-    }
-}
-
-ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
-{
-    ALOGV("write(%p, %u)", buffer, size);
-    if ((buffer == 0) || (size == 0)) return size;
-
-    uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
-    if (p == NULL) return NO_INIT;
-    p += mSize;
-    ALOGV("memcpy(%p, %p, %u)", p, buffer, size);
-
-    bool overflow = mSize + size > mHeap->getSize();
-    if (overflow) {
-        ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
-        size = mHeap->getSize() - mSize;
-    }
-    size -= size % mFrameSize; // consume only integral amounts of frame size
-    memcpy(p, buffer, size);
-    mSize += size;
-
-    if (overflow) {
-        // Signal heap filled here (last frame may be truncated).
-        // After this point, no more data should be written as the
-        // heap is filled and the AudioCache should be effectively
-        // immutable with respect to future writes.
-        //
-        // It is thus safe for another thread to read the AudioCache.
-        Mutex::Autolock lock(mLock);
-        mCommandComplete = true;
-        mSignal.signal();
-    }
-    return size;
-}
-
-// call with lock held
-status_t MediaPlayerService::AudioCache::wait()
-{
-    Mutex::Autolock lock(mLock);
-    while (!mCommandComplete) {
-        mSignal.wait(mLock);
-    }
-    mCommandComplete = false;
-
-    if (mError == NO_ERROR) {
-        ALOGV("wait - success");
-    } else {
-        ALOGV("wait - error");
-    }
-    return mError;
-}
-
-void MediaPlayerService::AudioCache::notify(
-        void* cookie, int msg, int ext1, int ext2, const Parcel* /*obj*/)
-{
-    ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
-    AudioCache* p = static_cast<AudioCache*>(cookie);
-
-    // ignore buffering messages
-    switch (msg)
-    {
-    case MEDIA_ERROR:
-        ALOGE("Error %d, %d occurred", ext1, ext2);
-        break;
-    case MEDIA_PREPARED:
-        ALOGV("prepared");
-        break;
-    case MEDIA_PLAYBACK_COMPLETE:
-        ALOGV("playback complete");
-        break;
-    default:
-        ALOGV("ignored");
-        return;
-    }
-
-    // wake up thread
-    Mutex::Autolock lock(p->mLock);
-    if (msg == MEDIA_ERROR) {
-        p->mError = ext1;
-    }
-    p->mCommandComplete = true;
-    p->mSignal.signal();
-}
-
-int MediaPlayerService::AudioCache::getSessionId() const
-{
-    return 0;
-}
-
-uint32_t MediaPlayerService::AudioCache::getSampleRate() const
-{
-    if (mMsecsPerFrame == 0) {
-        return 0;
-    }
-    return (uint32_t)(1.e3 / mMsecsPerFrame);
-}
-
 void MediaPlayerService::addBatteryData(uint32_t params)
 {
     Mutex::Autolock lock(mLock);
@@ -2234,7 +1916,7 @@
         return;
     }
 
-    // an sudio stream is started
+    // an audio stream is started
     if (params & kBatteryDataAudioFlingerStart) {
         // record the start time only if currently no other audio
         // is being played
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 3b96e88..fad3447 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -77,7 +77,6 @@
         virtual                 ~AudioOutput();
 
         virtual bool            ready() const { return mTrack != 0; }
-        virtual bool            realtime() const { return true; }
         virtual ssize_t         bufferSize() const;
         virtual ssize_t         frameCount() const;
         virtual ssize_t         channelCount() const;
@@ -184,75 +183,6 @@
     }; // AudioOutput
 
 
-    class AudioCache : public MediaPlayerBase::AudioSink
-    {
-    public:
-                                AudioCache(const sp<IMemoryHeap>& heap);
-        virtual                 ~AudioCache() {}
-
-        virtual bool            ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); }
-        virtual bool            realtime() const { return false; }
-        virtual ssize_t         bufferSize() const { return frameSize() * mFrameCount; }
-        virtual ssize_t         frameCount() const { return mFrameCount; }
-        virtual ssize_t         channelCount() const { return (ssize_t)mChannelCount; }
-        virtual ssize_t         frameSize() const { return (ssize_t)mFrameSize; }
-        virtual uint32_t        latency() const;
-        virtual float           msecsPerFrame() const;
-        virtual status_t        getPosition(uint32_t *position) const;
-        virtual status_t        getTimestamp(AudioTimestamp &ts) const;
-        virtual status_t        getFramesWritten(uint32_t *frameswritten) const;
-        virtual int             getSessionId() const;
-        virtual uint32_t        getSampleRate() const;
-
-        virtual status_t        open(
-                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
-                audio_format_t format, int bufferCount = 1,
-                AudioCallback cb = NULL, void *cookie = NULL,
-                audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
-                const audio_offload_info_t *offloadInfo = NULL);
-
-        virtual status_t        start();
-        virtual ssize_t         write(const void* buffer, size_t size);
-        virtual void            stop();
-        virtual void            flush() {}
-        virtual void            pause() {}
-        virtual void            close() {}
-                void            setAudioStreamType(audio_stream_type_t streamType __unused) {}
-                // stream type is not used for AudioCache
-        virtual audio_stream_type_t getAudioStreamType() const { return AUDIO_STREAM_DEFAULT; }
-
-                void            setVolume(float left __unused, float right __unused) {}
-        virtual status_t        setPlaybackRatePermille(int32_t ratePermille __unused) { return INVALID_OPERATION; }
-                uint32_t        sampleRate() const { return mSampleRate; }
-                audio_format_t  format() const { return mFormat; }
-                size_t          size() const { return mSize; }
-                status_t        wait();
-
-                sp<IMemoryHeap> getHeap() const { return mHeap; }
-
-        static  void            notify(void* cookie, int msg,
-                                       int ext1, int ext2, const Parcel *obj);
-        virtual status_t        dump(int fd, const Vector<String16>& args) const;
-
-    private:
-                                AudioCache();
-
-        Mutex               mLock;
-        Condition           mSignal;
-        sp<IMemoryHeap>     mHeap;
-        float               mMsecsPerFrame;
-        uint16_t            mChannelCount;
-        audio_format_t      mFormat;
-        ssize_t             mFrameCount;
-        uint32_t            mSampleRate;
-        uint32_t            mSize;
-        size_t              mFrameSize;
-        int                 mError;
-        bool                mCommandComplete;
-
-        sp<Thread>          mCallbackThread;
-    }; // AudioCache
-
 public:
     static  void                instantiate();
 
@@ -263,19 +193,6 @@
 
     virtual sp<IMediaPlayer>    create(const sp<IMediaPlayerClient>& client, int audioSessionId);
 
-    virtual status_t            decode(
-            const sp<IMediaHTTPService> &httpService,
-            const char* url,
-            uint32_t *pSampleRate,
-            int* pNumChannels,
-            audio_format_t* pFormat,
-            const sp<IMemoryHeap>& heap,
-            size_t *pSize);
-
-    virtual status_t            decode(int fd, int64_t offset, int64_t length,
-                                       uint32_t *pSampleRate, int* pNumChannels,
-                                       audio_format_t* pFormat,
-                                       const sp<IMemoryHeap>& heap, size_t *pSize);
     virtual sp<IMediaCodecList> getCodecList() const;
     virtual sp<IOMX>            getOMX();
     virtual sp<ICrypto>         makeCrypto();
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index 6609874..e2c72ed 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES:=                       \
         GenericSource.cpp               \
         HTTPLiveSource.cpp              \
+        MediaClock.cpp                  \
         NuPlayer.cpp                    \
         NuPlayerCCDecoder.cpp           \
         NuPlayerDecoder.cpp             \
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 76b80bb..9b446b8 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -40,6 +40,11 @@
 
 namespace android {
 
+static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
+static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
+static const ssize_t kLowWaterMarkBytes = 40000;
+static const ssize_t kHighWaterMarkBytes = 200000;
+
 NuPlayer::GenericSource::GenericSource(
         const sp<AMessage> &notify,
         bool uidValid,
@@ -55,6 +60,7 @@
       mAudioIsVorbis(false),
       mIsWidevine(false),
       mIsSecure(false),
+      mIsStreaming(false),
       mUIDValid(uidValid),
       mUID(uid),
       mFd(-1),
@@ -62,7 +68,9 @@
       mMetaDataSize(-1ll),
       mBitrate(-1ll),
       mPollBufferingGeneration(0),
-      mPendingReadBufferTypes(0) {
+      mPendingReadBufferTypes(0),
+      mBuffering(false),
+      mPrepareBuffering(false) {
     resetDataSource();
     DataSource::RegisterDefaultSniffers();
 }
@@ -254,6 +262,20 @@
         }
     }
 
+    // Start the selected A/V tracks now before we start buffering.
+    // Widevine sources might re-initialize crypto when starting, if we delay
+    // this to start(), all data buffered during prepare would be wasted.
+    // (We don't actually start reading until start().)
+    if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
+        ALOGE("failed to start audio track!");
+        return UNKNOWN_ERROR;
+    }
+
+    if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
+        ALOGE("failed to start video track!");
+        return UNKNOWN_ERROR;
+    }
+
     mBitrate = totalBitrate;
 
     return OK;
@@ -352,9 +374,13 @@
             mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
         }
 
-        if (mIsWidevine || mCachedSource != NULL) {
-            schedulePollBuffering();
-        }
+        // For widevine or other cached streaming cases, we need to wait for
+        // enough buffering before reporting prepared.
+        // Note that even when URL doesn't start with widevine://, mIsWidevine
+        // could still be set to true later, if the streaming or file source
+        // is sniffed to be widevine. We don't want to buffer for file source
+        // in that case, so must check the flag now.
+        mIsStreaming = (mIsWidevine || mCachedSource != NULL);
     }
 
     // check initial caching status
@@ -397,7 +423,14 @@
             | FLAG_CAN_SEEK_FORWARD
             | FLAG_CAN_SEEK);
 
-    notifyPrepared();
+    if (mIsStreaming) {
+        mPrepareBuffering = true;
+
+        ensureCacheIsFetching();
+        restartPollBuffering();
+    } else {
+        notifyPrepared();
+    }
 }
 
 void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
@@ -489,19 +522,17 @@
 
     mStopRead = false;
     if (mAudioTrack.mSource != NULL) {
-        CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
-
         postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
     }
 
     if (mVideoTrack.mSource != NULL) {
-        CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
-
         postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
     }
 
     setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
     mStarted = true;
+
+    (new AMessage(kWhatStart, id()))->post();
 }
 
 void NuPlayer::GenericSource::stop() {
@@ -526,6 +557,8 @@
     // nothing to do, just account for DRM playback status
     setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
     mStarted = true;
+
+    (new AMessage(kWhatResume, id()))->post();
 }
 
 void NuPlayer::GenericSource::disconnect() {
@@ -558,22 +591,98 @@
 }
 
 void NuPlayer::GenericSource::cancelPollBuffering() {
+    mBuffering = false;
     ++mPollBufferingGeneration;
 }
 
+void NuPlayer::GenericSource::restartPollBuffering() {
+    if (mIsStreaming) {
+        cancelPollBuffering();
+        onPollBuffering();
+    }
+}
+
 void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) {
+    ALOGV("notifyBufferingUpdate: buffering %d%%", percentage);
+
     sp<AMessage> msg = dupNotify();
     msg->setInt32("what", kWhatBufferingUpdate);
     msg->setInt32("percentage", percentage);
     msg->post();
 }
 
-void NuPlayer::GenericSource::onPollBuffering() {
-    status_t finalStatus = UNKNOWN_ERROR;
-    int64_t cachedDurationUs = 0ll;
+void NuPlayer::GenericSource::startBufferingIfNecessary() {
+    ALOGV("startBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d",
+            mPrepareBuffering, mBuffering);
+
+    if (mPrepareBuffering) {
+        return;
+    }
+
+    if (!mBuffering) {
+        mBuffering = true;
+
+        ensureCacheIsFetching();
+        sendCacheStats();
+
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatPauseOnBufferingStart);
+        notify->post();
+    }
+}
+
+void NuPlayer::GenericSource::stopBufferingIfNecessary() {
+    ALOGV("stopBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d",
+            mPrepareBuffering, mBuffering);
+
+    if (mPrepareBuffering) {
+        mPrepareBuffering = false;
+        notifyPrepared();
+        return;
+    }
+
+    if (mBuffering) {
+        mBuffering = false;
+
+        sendCacheStats();
+
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatResumeOnBufferingEnd);
+        notify->post();
+    }
+}
+
+void NuPlayer::GenericSource::sendCacheStats() {
+    int32_t kbps = 0;
+    status_t err = UNKNOWN_ERROR;
 
     if (mCachedSource != NULL) {
-        size_t cachedDataRemaining =
+        err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
+    } else if (mWVMExtractor != NULL) {
+        err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
+    }
+
+    if (err == OK) {
+        sp<AMessage> notify = dupNotify();
+        notify->setInt32("what", kWhatCacheStats);
+        notify->setInt32("bandwidth", kbps);
+        notify->post();
+    }
+}
+
+void NuPlayer::GenericSource::ensureCacheIsFetching() {
+    if (mCachedSource != NULL) {
+        mCachedSource->resumeFetchingIfNecessary();
+    }
+}
+
+void NuPlayer::GenericSource::onPollBuffering() {
+    status_t finalStatus = UNKNOWN_ERROR;
+    int64_t cachedDurationUs = -1ll;
+    ssize_t cachedDataRemaining = -1;
+
+    if (mCachedSource != NULL) {
+        cachedDataRemaining =
                 mCachedSource->approxDataRemaining(&finalStatus);
 
         if (finalStatus == OK) {
@@ -593,23 +702,48 @@
             = mWVMExtractor->getCachedDurationUs(&finalStatus);
     }
 
-    if (finalStatus == ERROR_END_OF_STREAM) {
-        notifyBufferingUpdate(100);
-        cancelPollBuffering();
-        return;
-    } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) {
-        int percentage = 100.0 * cachedDurationUs / mDurationUs;
-        if (percentage > 100) {
-            percentage = 100;
+    if (finalStatus != OK) {
+        ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);
+
+        if (finalStatus == ERROR_END_OF_STREAM) {
+            notifyBufferingUpdate(100);
         }
 
-        notifyBufferingUpdate(percentage);
+        stopBufferingIfNecessary();
+        return;
+    } else if (cachedDurationUs >= 0ll) {
+        if (mDurationUs > 0ll) {
+            int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs;
+            int percentage = 100.0 * cachedPosUs / mDurationUs;
+            if (percentage > 100) {
+                percentage = 100;
+            }
+
+            notifyBufferingUpdate(percentage);
+        }
+
+        ALOGV("onPollBuffering: cachedDurationUs %.1f sec",
+                cachedDurationUs / 1000000.0f);
+
+        if (cachedDurationUs < kLowWaterMarkUs) {
+            startBufferingIfNecessary();
+        } else if (cachedDurationUs > kHighWaterMarkUs) {
+            stopBufferingIfNecessary();
+        }
+    } else if (cachedDataRemaining >= 0) {
+        ALOGV("onPollBuffering: cachedDataRemaining %d bytes",
+                cachedDataRemaining);
+
+        if (cachedDataRemaining < kLowWaterMarkBytes) {
+            startBufferingIfNecessary();
+        } else if (cachedDataRemaining > kHighWaterMarkBytes) {
+            stopBufferingIfNecessary();
+        }
     }
 
     schedulePollBuffering();
 }
 
-
 void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
       case kWhatPrepareAsync:
@@ -688,6 +822,14 @@
 
           break;
       }
+
+      case kWhatStart:
+      case kWhatResume:
+      {
+          restartPollBuffering();
+          break;
+      }
+
       case kWhatPollBuffering:
       {
           int32_t generation;
@@ -1201,6 +1343,13 @@
     if (!mStarted) {
         setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0);
     }
+
+    // If currently buffering, post kWhatBufferingEnd first, so that
+    // NuPlayer resumes. Otherwise, if cache hits high watermark
+    // before new polling happens, no one will resume the playback.
+    stopBufferingIfNecessary();
+    restartPollBuffering();
+
     return OK;
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index 1b63a1f..385d73a 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -94,16 +94,17 @@
         kWhatSeek,
         kWhatReadBuffer,
         kWhatStopWidevine,
+        kWhatStart,
+        kWhatResume,
     };
 
-    Vector<sp<MediaSource> > mSources;
-
     struct Track {
         size_t mIndex;
         sp<MediaSource> mSource;
         sp<AnotherPacketSource> mPackets;
     };
 
+    Vector<sp<MediaSource> > mSources;
     Track mAudioTrack;
     int64_t mAudioTimeUs;
     int64_t mAudioLastDequeueTimeUs;
@@ -119,6 +120,7 @@
     bool mAudioIsVorbis;
     bool mIsWidevine;
     bool mIsSecure;
+    bool mIsStreaming;
     bool mUIDValid;
     uid_t mUID;
     sp<IMediaHTTPService> mHTTPService;
@@ -143,6 +145,8 @@
     int64_t mBitrate;
     int32_t mPollBufferingGeneration;
     uint32_t mPendingReadBufferTypes;
+    bool mBuffering;
+    bool mPrepareBuffering;
     mutable Mutex mReadBufferLock;
 
     sp<ALooper> mLooper;
@@ -194,8 +198,13 @@
 
     void schedulePollBuffering();
     void cancelPollBuffering();
+    void restartPollBuffering();
     void onPollBuffering();
     void notifyBufferingUpdate(int percentage);
+    void startBufferingIfNecessary();
+    void stopBufferingIfNecessary();
+    void sendCacheStats();
+    void ensureCacheIsFetching();
 
     DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
 };
diff --git a/media/libmediaplayerservice/nuplayer/MediaClock.cpp b/media/libmediaplayerservice/nuplayer/MediaClock.cpp
new file mode 100644
index 0000000..7bfff13
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/MediaClock.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaClock"
+#include <utils/Log.h>
+
+#include "MediaClock.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+
+namespace android {
+
+// Maximum time change between two updates.
+static const int64_t kMaxAnchorFluctuationUs = 1000ll;
+
+MediaClock::MediaClock()
+    : mAnchorTimeMediaUs(-1),
+      mAnchorTimeRealUs(-1),
+      mMaxTimeMediaUs(INT64_MAX),
+      mStartingTimeMediaUs(-1),
+      mPaused(false) {
+}
+
+MediaClock::~MediaClock() {
+}
+
+void MediaClock::setStartingTimeMedia(int64_t startingTimeMediaUs) {
+    Mutex::Autolock autoLock(mLock);
+    mStartingTimeMediaUs = startingTimeMediaUs;
+}
+
+void MediaClock::clearAnchor() {
+    Mutex::Autolock autoLock(mLock);
+    mAnchorTimeMediaUs = -1;
+    mAnchorTimeRealUs = -1;
+}
+
+void MediaClock::updateAnchor(
+        int64_t anchorTimeMediaUs,
+        int64_t anchorTimeRealUs,
+        int64_t maxTimeMediaUs) {
+    if (anchorTimeMediaUs < 0 || anchorTimeRealUs < 0) {
+        ALOGW("reject anchor time since it is negative.");
+        return;
+    }
+
+    int64_t nowUs = ALooper::GetNowUs();
+    int64_t nowMediaUs = anchorTimeMediaUs + nowUs - anchorTimeRealUs;
+    if (nowMediaUs < 0) {
+        ALOGW("reject anchor time since it leads to negative media time.");
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    mAnchorTimeRealUs = nowUs;
+    mAnchorTimeMediaUs = nowMediaUs;
+    mMaxTimeMediaUs = maxTimeMediaUs;
+}
+
+void MediaClock::updateMaxTimeMedia(int64_t maxTimeMediaUs) {
+    Mutex::Autolock autoLock(mLock);
+    mMaxTimeMediaUs = maxTimeMediaUs;
+}
+
+void MediaClock::pause() {
+    Mutex::Autolock autoLock(mLock);
+    if (mPaused) {
+        return;
+    }
+
+    mPaused = true;
+    if (mAnchorTimeRealUs == -1) {
+        return;
+    }
+
+    int64_t nowUs = ALooper::GetNowUs();
+    mAnchorTimeMediaUs += nowUs - mAnchorTimeRealUs;
+    if (mAnchorTimeMediaUs < 0) {
+        ALOGW("anchor time should not be negative, set to 0.");
+        mAnchorTimeMediaUs = 0;
+    }
+    mAnchorTimeRealUs = nowUs;
+}
+
+void MediaClock::resume() {
+    Mutex::Autolock autoLock(mLock);
+    if (!mPaused) {
+        return;
+    }
+
+    mPaused = false;
+    if (mAnchorTimeRealUs == -1) {
+        return;
+    }
+
+    mAnchorTimeRealUs = ALooper::GetNowUs();
+}
+
+int64_t MediaClock::getTimeMedia(int64_t realUs, bool allowPastMaxTime) {
+    Mutex::Autolock autoLock(mLock);
+    if (mAnchorTimeRealUs == -1) {
+        return -1ll;
+    }
+
+    if (mPaused) {
+        realUs = mAnchorTimeRealUs;
+    }
+    int64_t currentMediaUs = mAnchorTimeMediaUs + realUs - mAnchorTimeRealUs;
+    if (currentMediaUs > mMaxTimeMediaUs && !allowPastMaxTime) {
+        currentMediaUs = mMaxTimeMediaUs;
+    }
+    if (currentMediaUs < mStartingTimeMediaUs) {
+        currentMediaUs = mStartingTimeMediaUs;
+    }
+    if (currentMediaUs < 0) {
+        currentMediaUs = 0;
+    }
+    return currentMediaUs;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/MediaClock.h b/media/libmediaplayerservice/nuplayer/MediaClock.h
new file mode 100644
index 0000000..d005993
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/MediaClock.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef MEDIA_CLOCK_H_
+
+#define MEDIA_CLOCK_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct MediaClock : public RefBase {
+    MediaClock();
+
+    void setStartingTimeMedia(int64_t startingTimeMediaUs);
+
+    void clearAnchor();
+    // It's highly recommended to use timestamp of just rendered frame as
+    // anchor time, especially in paused state. Such restriction will be
+    // required when dynamic playback rate is supported in the future.
+    void updateAnchor(
+        int64_t anchorTimeMediaUs,
+        int64_t anchorTimeRealUs,
+        int64_t maxTimeMediaUs = INT64_MAX);
+
+    void updateMaxTimeMedia(int64_t maxTimeMediaUs);
+
+    void pause();
+    void resume();
+
+    int64_t getTimeMedia(int64_t realUs, bool allowPastMaxTime = false);
+
+protected:
+    virtual ~MediaClock();
+
+private:
+    Mutex mLock;
+
+    int64_t mAnchorTimeMediaUs;
+    int64_t mAnchorTimeRealUs;
+    int64_t mMaxTimeMediaUs;
+    int64_t mStartingTimeMediaUs;
+
+    bool mPaused;
+
+    DISALLOW_EVIL_CONSTRUCTORS(MediaClock);
+};
+
+}  // namespace android
+
+#endif  // MEDIA_CLOCK_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e02a2d5..1f55706 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -180,7 +180,9 @@
       mFlushingVideo(NONE),
       mResumePending(false),
       mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
-      mStarted(false) {
+      mStarted(false),
+      mPaused(false),
+      mPausedByClient(false) {
     clearFlushComplete();
 }
 
@@ -598,6 +600,7 @@
             } else {
                 onStart();
             }
+            mPausedByClient = false;
             break;
         }
 
@@ -956,16 +959,8 @@
 
         case kWhatPause:
         {
-            if (mSource != NULL) {
-                mSource->pause();
-            } else {
-                ALOGW("pause called when source is gone or not set");
-            }
-            if (mRenderer != NULL) {
-                mRenderer->pause();
-            } else {
-                ALOGW("pause called when renderer is gone or not set");
-            }
+            onPause();
+            mPausedByClient = true;
             break;
         }
 
@@ -988,6 +983,10 @@
 }
 
 void NuPlayer::onResume() {
+    if (!mPaused) {
+        return;
+    }
+    mPaused = false;
     if (mSource != NULL) {
         mSource->resume();
     } else {
@@ -1072,6 +1071,23 @@
     postScanSources();
 }
 
+void NuPlayer::onPause() {
+    if (mPaused) {
+        return;
+    }
+    mPaused = true;
+    if (mSource != NULL) {
+        mSource->pause();
+    } else {
+        ALOGW("pause called when source is gone or not set");
+    }
+    if (mRenderer != NULL) {
+        mRenderer->pause();
+    } else {
+        ALOGW("pause called when renderer is gone or not set");
+    }
+}
+
 bool NuPlayer::audioDecoderStillNeeded() {
     // Audio decoder is no longer needed if it's in shut/shutting down status.
     return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
@@ -1709,18 +1725,49 @@
             break;
         }
 
+        case Source::kWhatPauseOnBufferingStart:
+        {
+            // ignore if not playing
+            if (mStarted && !mPausedByClient) {
+                ALOGI("buffer low, pausing...");
+
+                onPause();
+            }
+            // fall-thru
+        }
+
         case Source::kWhatBufferingStart:
         {
             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
             break;
         }
 
+        case Source::kWhatResumeOnBufferingEnd:
+        {
+            // ignore if not playing
+            if (mStarted && !mPausedByClient) {
+                ALOGI("buffer ready, resuming...");
+
+                onResume();
+            }
+            // fall-thru
+        }
+
         case Source::kWhatBufferingEnd:
         {
             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
             break;
         }
 
+        case Source::kWhatCacheStats:
+        {
+            int32_t kbps;
+            CHECK(msg->findInt32("bandwidth", &kbps));
+
+            notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
+            break;
+        }
+
         case Source::kWhatSubtitleData:
         {
             sp<ABuffer> buffer;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index bb32eac..57eaf74 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -177,6 +177,14 @@
 
     bool mStarted;
 
+    // Actual pause state, either as requested by client or due to buffering.
+    bool mPaused;
+
+    // Pause state as requested by client. Note that if mPausedByClient is
+    // true, mPaused is always true; if mPausedByClient is false, mPaused could
+    // still become true, when we pause internally due to buffering.
+    bool mPausedByClient;
+
     inline const sp<DecoderBase> &getDecoder(bool audio) {
         return audio ? mAudioDecoder : mVideoDecoder;
     }
@@ -204,6 +212,7 @@
 
     void onStart();
     void onResume();
+    void onPause();
 
     bool audioDecoderStillNeeded();
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 2abd9d6..5d98d98 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -823,7 +823,7 @@
         const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
         for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
             int32_t oldVal, newVal;
-            if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
+            if (!mInputFormat->findInt32(keys[i], &oldVal) ||
                     !targetFormat->findInt32(keys[i], &newVal) ||
                     oldVal != newVal) {
                 return false;
@@ -831,7 +831,7 @@
         }
 
         sp<ABuffer> oldBuf, newBuf;
-        if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
+        if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
                 targetFormat->findBuffer("csd-0", &newBuf)) {
             if (oldBuf->size() != newBuf->size()) {
                 return false;
@@ -843,7 +843,7 @@
 }
 
 bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
-    if (mOutputFormat == NULL) {
+    if (mInputFormat == NULL) {
         return false;
     }
 
@@ -852,7 +852,7 @@
     }
 
     AString oldMime, newMime;
-    if (!mOutputFormat->findString("mime", &oldMime)
+    if (!mInputFormat->findString("mime", &oldMime)
             || !targetFormat->findString("mime", &newMime)
             || !(oldMime == newMime)) {
         return false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index f126b87..abfa4d3 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -662,8 +662,7 @@
                         mAutoLoop = false;
                     }
                 }
-                if (mLooping || (mAutoLoop
-                        && (mAudioSink == NULL || mAudioSink->realtime()))) {
+                if (mLooping || mAutoLoop) {
                     mPlayer->seekToAsync(0);
                     if (mAudioSink != NULL) {
                         // The renderer has stopped the sink at the end in order to play out
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 80b8493..83fc9e9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -20,6 +20,8 @@
 
 #include "NuPlayerRenderer.h"
 
+#include "MediaClock.h"
+
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -62,22 +64,18 @@
       mDrainVideoQueuePending(false),
       mAudioQueueGeneration(0),
       mVideoQueueGeneration(0),
+      mAudioDrainGeneration(0),
+      mVideoDrainGeneration(0),
       mAudioFirstAnchorTimeMediaUs(-1),
       mAnchorTimeMediaUs(-1),
-      mAnchorTimeRealUs(-1),
       mAnchorNumFramesWritten(-1),
-      mAnchorMaxMediaUs(-1),
       mVideoLateByUs(0ll),
       mHasAudio(false),
       mHasVideo(false),
-      mPauseStartedTimeRealUs(-1),
-      mFlushingAudio(false),
-      mFlushingVideo(false),
       mNotifyCompleteAudio(false),
       mNotifyCompleteVideo(false),
       mSyncQueues(false),
       mPaused(false),
-      mPausePositionMediaTimeUs(-1),
       mVideoSampleReceived(false),
       mVideoRenderingStarted(false),
       mVideoRenderingStartGeneration(0),
@@ -88,6 +86,7 @@
       mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER),
       mTotalBuffersQueued(0),
       mLastAudioBufferDrained(0) {
+    mMediaClock = new MediaClock;
 }
 
 NuPlayer::Renderer::~Renderer() {
@@ -103,6 +102,7 @@
         const sp<ABuffer> &buffer,
         const sp<AMessage> &notifyConsumed) {
     sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
+    msg->setInt32("queueGeneration", getQueueGeneration(audio));
     msg->setInt32("audio", static_cast<int32_t>(audio));
     msg->setBuffer("buffer", buffer);
     msg->setMessage("notifyConsumed", notifyConsumed);
@@ -113,6 +113,7 @@
     CHECK_NE(finalResult, (status_t)OK);
 
     sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
+    msg->setInt32("queueGeneration", getQueueGeneration(audio));
     msg->setInt32("audio", static_cast<int32_t>(audio));
     msg->setInt32("finalResult", finalResult);
     msg->post();
@@ -120,20 +121,21 @@
 
 void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
     {
-        Mutex::Autolock autoLock(mFlushLock);
+        Mutex::Autolock autoLock(mLock);
         if (audio) {
             mNotifyCompleteAudio |= notifyComplete;
-            if (mFlushingAudio) {
-                return;
-            }
-            mFlushingAudio = true;
+            ++mAudioQueueGeneration;
+            ++mAudioDrainGeneration;
         } else {
             mNotifyCompleteVideo |= notifyComplete;
-            if (mFlushingVideo) {
-                return;
-            }
-            mFlushingVideo = true;
+            ++mVideoQueueGeneration;
+            ++mVideoDrainGeneration;
         }
+
+        clearAnchorTime_l();
+        clearAudioFirstAnchorTime_l();
+        mVideoLateByUs = 0;
+        mSyncQueues = false;
     }
 
     sp<AMessage> msg = new AMessage(kWhatFlush, id());
@@ -142,17 +144,6 @@
 }
 
 void NuPlayer::Renderer::signalTimeDiscontinuity() {
-    Mutex::Autolock autoLock(mLock);
-    // CHECK(mAudioQueue.empty());
-    // CHECK(mVideoQueue.empty());
-    setAudioFirstAnchorTime(-1);
-    setAnchorTime(-1, -1);
-    setVideoLateByUs(0);
-    mSyncQueues = false;
-}
-
-void NuPlayer::Renderer::signalAudioSinkChanged() {
-    (new AMessage(kWhatAudioSinkChanged, id()))->post();
 }
 
 void NuPlayer::Renderer::signalDisableOffloadAudio() {
@@ -177,127 +168,44 @@
     msg->post();
 }
 
-// Called on any threads, except renderer's thread.
-status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
-    {
-        Mutex::Autolock autoLock(mLock);
-        int64_t currentPositionUs;
-        if (getCurrentPositionIfPaused_l(&currentPositionUs)) {
-            *mediaUs = currentPositionUs;
-            return OK;
-        }
-    }
-    return getCurrentPositionFromAnchor(mediaUs, ALooper::GetNowUs());
-}
-
-// Called on only renderer's thread.
-status_t NuPlayer::Renderer::getCurrentPositionOnLooper(int64_t *mediaUs) {
-    return getCurrentPositionOnLooper(mediaUs, ALooper::GetNowUs());
-}
-
-// Called on only renderer's thread.
-// Since mPaused and mPausePositionMediaTimeUs are changed only on renderer's
-// thread, no need to acquire mLock.
-status_t NuPlayer::Renderer::getCurrentPositionOnLooper(
-        int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
-    int64_t currentPositionUs;
-    if (getCurrentPositionIfPaused_l(&currentPositionUs)) {
-        *mediaUs = currentPositionUs;
-        return OK;
-    }
-    return getCurrentPositionFromAnchor(mediaUs, nowUs, allowPastQueuedVideo);
-}
-
-// Called either with mLock acquired or on renderer's thread.
-bool NuPlayer::Renderer::getCurrentPositionIfPaused_l(int64_t *mediaUs) {
-    if (!mPaused || mPausePositionMediaTimeUs < 0ll) {
-        return false;
-    }
-    *mediaUs = mPausePositionMediaTimeUs;
-    return true;
-}
-
 // Called on any threads.
-status_t NuPlayer::Renderer::getCurrentPositionFromAnchor(
-        int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) {
-    Mutex::Autolock autoLock(mTimeLock);
-    if (!mHasAudio && !mHasVideo) {
+status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
+    int64_t currentTimeUs = mMediaClock->getTimeMedia(ALooper::GetNowUs());
+    if (currentTimeUs == -1) {
         return NO_INIT;
     }
-
-    if (mAnchorTimeMediaUs < 0) {
-        return NO_INIT;
-    }
-
-    int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
-
-    if (mPauseStartedTimeRealUs != -1) {
-        positionUs -= (nowUs - mPauseStartedTimeRealUs);
-    }
-
-    // limit position to the last queued media time (for video only stream
-    // position will be discrete as we don't know how long each frame lasts)
-    if (mAnchorMaxMediaUs >= 0 && !allowPastQueuedVideo) {
-        if (positionUs > mAnchorMaxMediaUs) {
-            positionUs = mAnchorMaxMediaUs;
-        }
-    }
-
-    if (positionUs < mAudioFirstAnchorTimeMediaUs) {
-        positionUs = mAudioFirstAnchorTimeMediaUs;
-    }
-
-    *mediaUs = (positionUs <= 0) ? 0 : positionUs;
+    *mediaUs = currentTimeUs;
     return OK;
 }
 
-void NuPlayer::Renderer::setHasMedia(bool audio) {
-    Mutex::Autolock autoLock(mTimeLock);
-    if (audio) {
-        mHasAudio = true;
-    } else {
-        mHasVideo = true;
-    }
+void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
+    mAudioFirstAnchorTimeMediaUs = -1;
+    mMediaClock->setStartingTimeMedia(-1);
 }
 
-void NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) {
-    Mutex::Autolock autoLock(mTimeLock);
-    mAudioFirstAnchorTimeMediaUs = mediaUs;
-}
-
-void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) {
-    Mutex::Autolock autoLock(mTimeLock);
+void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs) {
     if (mAudioFirstAnchorTimeMediaUs == -1) {
         mAudioFirstAnchorTimeMediaUs = mediaUs;
+        mMediaClock->setStartingTimeMedia(mediaUs);
     }
 }
 
-void NuPlayer::Renderer::setAnchorTime(
-        int64_t mediaUs, int64_t realUs, int64_t numFramesWritten, bool resume) {
-    Mutex::Autolock autoLock(mTimeLock);
-    mAnchorTimeMediaUs = mediaUs;
-    mAnchorTimeRealUs = realUs;
-    mAnchorNumFramesWritten = numFramesWritten;
-    if (resume) {
-        mPauseStartedTimeRealUs = -1;
-    }
+void NuPlayer::Renderer::clearAnchorTime_l() {
+    mMediaClock->clearAnchor();
+    mAnchorTimeMediaUs = -1;
+    mAnchorNumFramesWritten = -1;
 }
 
 void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
-    Mutex::Autolock autoLock(mTimeLock);
+    Mutex::Autolock autoLock(mLock);
     mVideoLateByUs = lateUs;
 }
 
 int64_t NuPlayer::Renderer::getVideoLateByUs() {
-    Mutex::Autolock autoLock(mTimeLock);
+    Mutex::Autolock autoLock(mLock);
     return mVideoLateByUs;
 }
 
-void NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) {
-    Mutex::Autolock autoLock(mTimeLock);
-    mPauseStartedTimeRealUs = realUs;
-}
-
 status_t NuPlayer::Renderer::openAudioSink(
         const sp<AMessage> &format,
         bool offloadOnly,
@@ -381,8 +289,8 @@
         case kWhatDrainAudioQueue:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mAudioQueueGeneration) {
+            CHECK(msg->findInt32("drainGeneration", &generation));
+            if (generation != getDrainGeneration(true /* audio */)) {
                 break;
             }
 
@@ -404,9 +312,7 @@
 
                 // Let's give it more data after about half that time
                 // has elapsed.
-                // kWhatDrainAudioQueue is used for non-offloading mode,
-                // and mLock is used only for offloading mode. Therefore,
-                // no need to acquire mLock here.
+                Mutex::Autolock autoLock(mLock);
                 postDrainAudioQueue_l(delayUs / 2);
             }
             break;
@@ -415,8 +321,8 @@
         case kWhatDrainVideoQueue:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mVideoQueueGeneration) {
+            CHECK(msg->findInt32("drainGeneration", &generation));
+            if (generation != getDrainGeneration(false /* audio */)) {
                 break;
             }
 
@@ -431,8 +337,8 @@
         case kWhatPostDrainVideoQueue:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
-            if (generation != mVideoQueueGeneration) {
+            CHECK(msg->findInt32("drainGeneration", &generation));
+            if (generation != getDrainGeneration(false /* audio */)) {
                 break;
             }
 
@@ -459,12 +365,6 @@
             break;
         }
 
-        case kWhatAudioSinkChanged:
-        {
-            onAudioSinkChanged();
-            break;
-        }
-
         case kWhatDisableOffloadAudio:
         {
             onDisableOffloadAudio();
@@ -506,7 +406,7 @@
         case kWhatAudioOffloadPauseTimeout:
         {
             int32_t generation;
-            CHECK(msg->findInt32("generation", &generation));
+            CHECK(msg->findInt32("drainGeneration", &generation));
             if (generation != mAudioOffloadPauseTimeoutGeneration) {
                 break;
             }
@@ -533,18 +433,18 @@
 
     mDrainAudioQueuePending = true;
     sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
-    msg->setInt32("generation", mAudioQueueGeneration);
+    msg->setInt32("drainGeneration", mAudioDrainGeneration);
     msg->post(delayUs);
 }
 
-void NuPlayer::Renderer::prepareForMediaRenderingStart() {
-    mAudioRenderingStartGeneration = mAudioQueueGeneration;
-    mVideoRenderingStartGeneration = mVideoQueueGeneration;
+void NuPlayer::Renderer::prepareForMediaRenderingStart_l() {
+    mAudioRenderingStartGeneration = mAudioDrainGeneration;
+    mVideoRenderingStartGeneration = mVideoDrainGeneration;
 }
 
-void NuPlayer::Renderer::notifyIfMediaRenderingStarted() {
-    if (mVideoRenderingStartGeneration == mVideoQueueGeneration &&
-        mAudioRenderingStartGeneration == mAudioQueueGeneration) {
+void NuPlayer::Renderer::notifyIfMediaRenderingStarted_l() {
+    if (mVideoRenderingStartGeneration == mVideoDrainGeneration &&
+        mAudioRenderingStartGeneration == mAudioDrainGeneration) {
         mVideoRenderingStartGeneration = -1;
         mAudioRenderingStartGeneration = -1;
 
@@ -612,7 +512,7 @@
             int64_t mediaTimeUs;
             CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
             ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
-            setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
+            setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
         }
 
         size_t copy = entry->mBuffer->size() - entry->mOffset;
@@ -632,17 +532,18 @@
             entry = NULL;
         }
         sizeCopied += copy;
-        notifyIfMediaRenderingStarted();
+
+        notifyIfMediaRenderingStarted_l();
     }
 
     if (mAudioFirstAnchorTimeMediaUs >= 0) {
         int64_t nowUs = ALooper::GetNowUs();
-        setAnchorTime(mAudioFirstAnchorTimeMediaUs, nowUs - getPlayedOutAudioDurationUs(nowUs));
+        // we don't know how much data we are queueing for offloaded tracks.
+        mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs,
+                                  nowUs - getPlayedOutAudioDurationUs(nowUs),
+                                  INT64_MAX);
     }
 
-    // we don't know how much data we are queueing for offloaded tracks
-    mAnchorMaxMediaUs = -1;
-
     if (hasEOS) {
         (new AMessage(kWhatStopAudioSink, id()))->post();
     }
@@ -727,7 +628,10 @@
         size_t copiedFrames = written / mAudioSink->frameSize();
         mNumFramesWritten += copiedFrames;
 
-        notifyIfMediaRenderingStarted();
+        {
+            Mutex::Autolock autoLock(mLock);
+            notifyIfMediaRenderingStarted_l();
+        }
 
         if (written != (ssize_t)copy) {
             // A short count was received from AudioSink::write()
@@ -750,10 +654,15 @@
             break;
         }
     }
-    mAnchorMaxMediaUs =
-        mAnchorTimeMediaUs +
-                (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
-                        * 1000LL * mAudioSink->msecsPerFrame());
+    int64_t maxTimeMedia;
+    {
+        Mutex::Autolock autoLock(mLock);
+        maxTimeMedia =
+            mAnchorTimeMediaUs +
+                    (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL)
+                            * 1000LL * mAudioSink->msecsPerFrame());
+    }
+    mMediaClock->updateMaxTimeMedia(maxTimeMedia);
 
     return !mAudioQueue.empty();
 }
@@ -765,31 +674,35 @@
 }
 
 int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
-    int64_t currentPositionUs;
-    if (getCurrentPositionOnLooper(
-            &currentPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) {
-        // If failed to get current position, e.g. due to audio clock is not ready, then just
-        // play out video immediately without delay.
+    int64_t currentPositionUs =
+            mMediaClock->getTimeMedia(nowUs, true /* allowPastMaxTime */);
+    if (currentPositionUs == -1) {
+        // If failed to get current position, e.g. due to audio clock is
+        // not ready, then just play out video immediately without delay.
         return nowUs;
     }
     return (mediaTimeUs - currentPositionUs) + nowUs;
 }
 
 void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
+    Mutex::Autolock autoLock(mLock);
     // TRICKY: vorbis decoder generates multiple frames with the same
     // timestamp, so only update on the first frame with a given timestamp
     if (mediaTimeUs == mAnchorTimeMediaUs) {
         return;
     }
-    setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
+    setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
     int64_t nowUs = ALooper::GetNowUs();
-    setAnchorTime(
-            mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs), mNumFramesWritten);
+    mMediaClock->updateAnchor(mediaTimeUs,
+                              nowUs + getPendingAudioPlayoutDurationUs(nowUs),
+                              mediaTimeUs);
+    mAnchorTimeMediaUs = mediaTimeUs;
 }
 
+// Called without mLock acquired.
 void NuPlayer::Renderer::postDrainVideoQueue() {
     if (mDrainVideoQueuePending
-            || mSyncQueues
+            || getSyncQueues()
             || (mPaused && mVideoSampleReceived)) {
         return;
     }
@@ -801,7 +714,7 @@
     QueueEntry &entry = *mVideoQueue.begin();
 
     sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
-    msg->setInt32("generation", mVideoQueueGeneration);
+    msg->setInt32("drainGeneration", getDrainGeneration(false /* audio */));
 
     if (entry.mBuffer == NULL) {
         // EOS doesn't carry a timestamp.
@@ -821,15 +734,19 @@
         int64_t mediaTimeUs;
         CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
 
-        if (mAnchorTimeMediaUs < 0) {
-            setAnchorTime(mediaTimeUs, nowUs);
-            mAnchorMaxMediaUs = mediaTimeUs;
-            realTimeUs = nowUs;
-        } else {
-            realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
+        {
+            Mutex::Autolock autoLock(mLock);
+            if (mAnchorTimeMediaUs < 0) {
+                mMediaClock->updateAnchor(mediaTimeUs, nowUs, mediaTimeUs);
+                mAnchorTimeMediaUs = mediaTimeUs;
+                realTimeUs = nowUs;
+            } else {
+                realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
+            }
         }
         if (!mHasAudio) {
-            mAnchorMaxMediaUs = mediaTimeUs + 100000; // smooth out videos >= 10fps
+            // smooth out videos >= 10fps
+            mMediaClock->updateMaxTimeMedia(mediaTimeUs + 100000);
         }
 
         // Heuristics to handle situation when media time changed without a
@@ -910,14 +827,15 @@
         } else {
             ALOGV("rendering video at media time %.2f secs",
                     (mFlags & FLAG_REAL_TIME ? realTimeUs :
-                    (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
+                    mMediaClock->getTimeMedia(realTimeUs)) / 1E6);
         }
     } else {
         setVideoLateByUs(0);
         if (!mVideoSampleReceived && !mHasAudio) {
             // This will ensure that the first frame after a flush won't be used as anchor
             // when renderer is in paused state, because resume can happen any time after seek.
-            setAnchorTime(-1, -1);
+            Mutex::Autolock autoLock(mLock);
+            clearAnchorTime_l();
         }
     }
 
@@ -934,7 +852,8 @@
             mVideoRenderingStarted = true;
             notifyVideoRenderingStart();
         }
-        notifyIfMediaRenderingStarted();
+        Mutex::Autolock autoLock(mLock);
+        notifyIfMediaRenderingStarted_l();
     }
 }
 
@@ -960,7 +879,15 @@
     int32_t audio;
     CHECK(msg->findInt32("audio", &audio));
 
-    setHasMedia(audio);
+    if (dropBufferIfStale(audio, msg)) {
+        return;
+    }
+
+    if (audio) {
+        mHasAudio = true;
+    } else {
+        mHasVideo = true;
+    }
 
     if (mHasVideo) {
         if (mVideoScheduler == NULL) {
@@ -969,10 +896,6 @@
         }
     }
 
-    if (dropBufferWhileFlushing(audio, msg)) {
-        return;
-    }
-
     sp<ABuffer> buffer;
     CHECK(msg->findBuffer("buffer", &buffer));
 
@@ -1044,7 +967,9 @@
     }
 
     if (!mVideoQueue.empty()) {
+        mLock.unlock();
         postDrainVideoQueue();
+        mLock.lock();
     }
 }
 
@@ -1052,7 +977,7 @@
     int32_t audio;
     CHECK(msg->findInt32("audio", &audio));
 
-    if (dropBufferWhileFlushing(audio, msg)) {
+    if (dropBufferIfStale(audio, msg)) {
         return;
     }
 
@@ -1071,7 +996,7 @@
         mAudioQueue.push_back(entry);
         postDrainAudioQueue_l();
     } else {
-        if (mVideoQueue.empty() && mSyncQueues) {
+        if (mVideoQueue.empty() && getSyncQueues()) {
             Mutex::Autolock autoLock(mLock);
             syncQueuesDone_l();
         }
@@ -1085,31 +1010,25 @@
     CHECK(msg->findInt32("audio", &audio));
 
     {
-        Mutex::Autolock autoLock(mFlushLock);
+        Mutex::Autolock autoLock(mLock);
         if (audio) {
-            mFlushingAudio = false;
             notifyComplete = mNotifyCompleteAudio;
             mNotifyCompleteAudio = false;
         } else {
-            mFlushingVideo = false;
             notifyComplete = mNotifyCompleteVideo;
             mNotifyCompleteVideo = false;
         }
-    }
 
-    // If we're currently syncing the queues, i.e. dropping audio while
-    // aligning the first audio/video buffer times and only one of the
-    // two queues has data, we may starve that queue by not requesting
-    // more buffers from the decoder. If the other source then encounters
-    // a discontinuity that leads to flushing, we'll never find the
-    // corresponding discontinuity on the other queue.
-    // Therefore we'll stop syncing the queues if at least one of them
-    // is flushed.
-    {
-         Mutex::Autolock autoLock(mLock);
-         syncQueuesDone_l();
-         setPauseStartedTimeRealUs(-1);
-         setAnchorTime(-1, -1);
+        // If we're currently syncing the queues, i.e. dropping audio while
+        // aligning the first audio/video buffer times and only one of the
+        // two queues has data, we may starve that queue by not requesting
+        // more buffers from the decoder. If the other source then encounters
+        // a discontinuity that leads to flushing, we'll never find the
+        // corresponding discontinuity on the other queue.
+        // Therefore we'll stop syncing the queues if at least one of them
+        // is flushed.
+        syncQueuesDone_l();
+        clearAnchorTime_l();
     }
 
     ALOGV("flushing %s", audio ? "audio" : "video");
@@ -1118,11 +1037,11 @@
             Mutex::Autolock autoLock(mLock);
             flushQueue(&mAudioQueue);
 
-            ++mAudioQueueGeneration;
-            prepareForMediaRenderingStart();
+            ++mAudioDrainGeneration;
+            prepareForMediaRenderingStart_l();
 
             if (offloadingAudio()) {
-                setAudioFirstAnchorTime(-1);
+                clearAudioFirstAnchorTime_l();
             }
         }
 
@@ -1137,13 +1056,14 @@
         flushQueue(&mVideoQueue);
 
         mDrainVideoQueuePending = false;
-        ++mVideoQueueGeneration;
 
         if (mVideoScheduler != NULL) {
             mVideoScheduler->restart();
         }
 
-        prepareForMediaRenderingStart();
+        Mutex::Autolock autoLock(mLock);
+        ++mVideoDrainGeneration;
+        prepareForMediaRenderingStart_l();
     }
 
     mVideoSampleReceived = false;
@@ -1173,20 +1093,12 @@
     notify->post();
 }
 
-bool NuPlayer::Renderer::dropBufferWhileFlushing(
+bool NuPlayer::Renderer::dropBufferIfStale(
         bool audio, const sp<AMessage> &msg) {
-    bool flushing = false;
+    int32_t queueGeneration;
+    CHECK(msg->findInt32("queueGeneration", &queueGeneration));
 
-    {
-        Mutex::Autolock autoLock(mFlushLock);
-        if (audio) {
-            flushing = mFlushingAudio;
-        } else {
-            flushing = mFlushingVideo;
-        }
-    }
-
-    if (!flushing) {
+    if (queueGeneration == getQueueGeneration(audio)) {
         return false;
     }
 
@@ -1204,7 +1116,10 @@
     }
     CHECK(!mDrainAudioQueuePending);
     mNumFramesWritten = 0;
-    mAnchorNumFramesWritten = -1;
+    {
+        Mutex::Autolock autoLock(mLock);
+        mAnchorNumFramesWritten = -1;
+    }
     uint32_t written;
     if (mAudioSink->getFramesWritten(&written) == OK) {
         mNumFramesWritten = written;
@@ -1214,13 +1129,13 @@
 void NuPlayer::Renderer::onDisableOffloadAudio() {
     Mutex::Autolock autoLock(mLock);
     mFlags &= ~FLAG_OFFLOAD_AUDIO;
-    ++mAudioQueueGeneration;
+    ++mAudioDrainGeneration;
 }
 
 void NuPlayer::Renderer::onEnableOffloadAudio() {
     Mutex::Autolock autoLock(mLock);
     mFlags |= FLAG_OFFLOAD_AUDIO;
-    ++mAudioQueueGeneration;
+    ++mAudioDrainGeneration;
 }
 
 void NuPlayer::Renderer::onPause() {
@@ -1229,23 +1144,13 @@
         return;
     }
     int64_t currentPositionUs;
-    if (getCurrentPositionFromAnchor(
-            &currentPositionUs, ALooper::GetNowUs()) == OK) {
-        mPausePositionMediaTimeUs = currentPositionUs;
-    } else {
-        // Set paused position to -1 (unavailabe) if we don't have anchor time
-        // This could happen if client does a seekTo() immediately followed by
-        // pause(). Renderer will be flushed with anchor time cleared. We don't
-        // want to leave stale value in mPausePositionMediaTimeUs.
-        mPausePositionMediaTimeUs = -1;
-    }
     {
         Mutex::Autolock autoLock(mLock);
-        ++mAudioQueueGeneration;
-        ++mVideoQueueGeneration;
-        prepareForMediaRenderingStart();
+        ++mAudioDrainGeneration;
+        ++mVideoDrainGeneration;
+        prepareForMediaRenderingStart_l();
         mPaused = true;
-        setPauseStartedTimeRealUs(ALooper::GetNowUs());
+        mMediaClock->pause();
     }
 
     mDrainAudioQueuePending = false;
@@ -1270,17 +1175,14 @@
         mAudioSink->start();
     }
 
-    Mutex::Autolock autoLock(mLock);
-    mPaused = false;
-    if (mPauseStartedTimeRealUs != -1) {
-        int64_t newAnchorRealUs =
-            mAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs;
-        setAnchorTime(
-                mAnchorTimeMediaUs, newAnchorRealUs, mAnchorNumFramesWritten, true /* resume */);
-    }
+    {
+        Mutex::Autolock autoLock(mLock);
+        mPaused = false;
+        mMediaClock->resume();
 
-    if (!mAudioQueue.empty()) {
-        postDrainAudioQueue_l();
+        if (!mAudioQueue.empty()) {
+            postDrainAudioQueue_l();
+        }
     }
 
     if (!mVideoQueue.empty()) {
@@ -1295,6 +1197,21 @@
     mVideoScheduler->init(fps);
 }
 
+int32_t NuPlayer::Renderer::getQueueGeneration(bool audio) {
+    Mutex::Autolock autoLock(mLock);
+    return (audio ? mAudioQueueGeneration : mVideoQueueGeneration);
+}
+
+int32_t NuPlayer::Renderer::getDrainGeneration(bool audio) {
+    Mutex::Autolock autoLock(mLock);
+    return (audio ? mAudioDrainGeneration : mVideoDrainGeneration);
+}
+
+bool NuPlayer::Renderer::getSyncQueues() {
+    Mutex::Autolock autoLock(mLock);
+    return mSyncQueues;
+}
+
 // TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs()
 // as it acquires locks and may query the audio driver.
 //
@@ -1366,7 +1283,7 @@
     mAudioOffloadTornDown = true;
 
     int64_t currentPositionUs;
-    if (getCurrentPositionOnLooper(&currentPositionUs) != OK) {
+    if (getCurrentPosition(&currentPositionUs) != OK) {
         currentPositionUs = 0;
     }
 
@@ -1383,7 +1300,7 @@
 void NuPlayer::Renderer::startAudioOffloadPauseTimeout() {
     if (offloadingAudio()) {
         sp<AMessage> msg = new AMessage(kWhatAudioOffloadPauseTimeout, id());
-        msg->setInt32("generation", mAudioOffloadPauseTimeoutGeneration);
+        msg->setInt32("drainGeneration", mAudioOffloadPauseTimeoutGeneration);
         msg->post(kOffloadPauseMaxUs);
     }
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 23907c8..b35c86a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -23,6 +23,7 @@
 namespace android {
 
 struct ABuffer;
+struct MediaClock;
 struct VideoFrameScheduler;
 
 struct NuPlayer::Renderer : public AHandler {
@@ -60,16 +61,8 @@
 
     void setVideoFrameRate(float fps);
 
-    // Following setters and getters are protected by mTimeLock.
     status_t getCurrentPosition(int64_t *mediaUs);
-    void setHasMedia(bool audio);
-    void setAudioFirstAnchorTime(int64_t mediaUs);
-    void setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs);
-    void setAnchorTime(
-            int64_t mediaUs, int64_t realUs, int64_t numFramesWritten = -1, bool resume = false);
-    void setVideoLateByUs(int64_t lateUs);
     int64_t getVideoLateByUs();
-    void setPauseStartedTimeRealUs(int64_t realUs);
 
     status_t openAudioSink(
             const sp<AMessage> &format,
@@ -107,7 +100,6 @@
         kWhatQueueBuffer         = 'queB',
         kWhatQueueEOS            = 'qEOS',
         kWhatFlush               = 'flus',
-        kWhatAudioSinkChanged    = 'auSC',
         kWhatPause               = 'paus',
         kWhatResume              = 'resm',
         kWhatOpenAudioSink       = 'opnA',
@@ -141,26 +133,17 @@
     bool mDrainVideoQueuePending;
     int32_t mAudioQueueGeneration;
     int32_t mVideoQueueGeneration;
+    int32_t mAudioDrainGeneration;
+    int32_t mVideoDrainGeneration;
 
-    Mutex mTimeLock;
-    // |mTimeLock| protects the following 7 member vars that are related to time.
-    // Note: those members are only written on Renderer thread, so reading on Renderer thread
-    // doesn't need to be protected. Otherwise accessing those members must be protected by
-    // |mTimeLock|.
-    // TODO: move those members to a seperated media clock class.
+    sp<MediaClock> mMediaClock;
     int64_t mAudioFirstAnchorTimeMediaUs;
     int64_t mAnchorTimeMediaUs;
-    int64_t mAnchorTimeRealUs;
     int64_t mAnchorNumFramesWritten;
-    int64_t mAnchorMaxMediaUs;
     int64_t mVideoLateByUs;
     bool mHasAudio;
     bool mHasVideo;
-    int64_t mPauseStartedTimeRealUs;
 
-    Mutex mFlushLock;  // protects the following 2 member vars.
-    bool mFlushingAudio;
-    bool mFlushingVideo;
     bool mNotifyCompleteAudio;
     bool mNotifyCompleteVideo;
 
@@ -168,7 +151,6 @@
 
     // modified on only renderer's thread.
     bool mPaused;
-    int64_t mPausePositionMediaTimeUs;
 
     bool mVideoSampleReceived;
     bool mVideoRenderingStarted;
@@ -194,13 +176,6 @@
     int32_t mTotalBuffersQueued;
     int32_t mLastAudioBufferDrained;
 
-    status_t getCurrentPositionOnLooper(int64_t *mediaUs);
-    status_t getCurrentPositionOnLooper(
-            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
-    bool getCurrentPositionIfPaused_l(int64_t *mediaUs);
-    status_t getCurrentPositionFromAnchor(
-            int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false);
-
     size_t fillAudioBuffer(void *buffer, size_t size);
 
     bool onDrainAudioQueue();
@@ -208,14 +183,19 @@
     int64_t getPlayedOutAudioDurationUs(int64_t nowUs);
     void postDrainAudioQueue_l(int64_t delayUs = 0);
 
+    void clearAnchorTime_l();
+    void clearAudioFirstAnchorTime_l();
+    void setAudioFirstAnchorTimeIfNeeded_l(int64_t mediaUs);
+    void setVideoLateByUs(int64_t lateUs);
+
     void onNewAudioMediaTime(int64_t mediaTimeUs);
     int64_t getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs);
 
     void onDrainVideoQueue();
     void postDrainVideoQueue();
 
-    void prepareForMediaRenderingStart();
-    void notifyIfMediaRenderingStarted();
+    void prepareForMediaRenderingStart_l();
+    void notifyIfMediaRenderingStarted_l();
 
     void onQueueBuffer(const sp<AMessage> &msg);
     void onQueueEOS(const sp<AMessage> &msg);
@@ -226,6 +206,9 @@
     void onPause();
     void onResume();
     void onSetVideoFrameRate(float fps);
+    int32_t getQueueGeneration(bool audio);
+    int32_t getDrainGeneration(bool audio);
+    bool getSyncQueues();
     void onAudioOffloadTearDown(AudioOffloadTearDownReason reason);
     status_t onOpenAudioSink(
             const sp<AMessage> &format,
@@ -242,7 +225,7 @@
     void notifyAudioOffloadTearDown();
 
     void flushQueue(List<QueueEntry> *queue);
-    bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
+    bool dropBufferIfStale(bool audio, const sp<AMessage> &msg);
     void syncQueuesDone_l();
 
     bool offloadingAudio() const { return (mFlags & FLAG_OFFLOAD_AUDIO) != 0; }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index c81d3b9..5a8beb1 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -48,6 +48,9 @@
         kWhatBufferingUpdate,
         kWhatBufferingStart,
         kWhatBufferingEnd,
+        kWhatPauseOnBufferingStart,
+        kWhatResumeOnBufferingEnd,
+        kWhatCacheStats,
         kWhatSubtitleData,
         kWhatTimedTextData,
         kWhatQueueDecoderShutdown,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index fa31c44..6a84c11 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1258,8 +1258,8 @@
     }
 
     sp<RefBase> obj;
-    int32_t haveNativeWindow = msg->findObject("native-window", &obj) &&
-        obj != NULL;
+    bool haveNativeWindow = msg->findObject("native-window", &obj)
+            && obj != NULL;
     mStoreMetaDataInOutputBuffers = false;
     if (video && !encoder) {
         inputFormat->setInt32("adaptive-playback", false);
@@ -1333,6 +1333,15 @@
             ALOGV("Configuring CPU controlled video playback.");
             mTunneled = false;
 
+            // Explicity reset the sideband handle of the window for
+            // non-tunneled video in case the window was previously used
+            // for a tunneled video playback.
+            err = native_window_set_sideband_stream(nativeWindow.get(), NULL);
+            if (err != OK) {
+                ALOGE("set_sideband_stream(NULL) failed! (err %d).", err);
+                return err;
+            }
+
             // Always try to enable dynamic output buffers on native surface
             err = mOMX->storeMetaDataInBuffers(
                     mNode, kPortIndexOutput, OMX_TRUE);
@@ -1410,7 +1419,7 @@
         if (encoder) {
             err = setupVideoEncoder(mime, msg);
         } else {
-            err = setupVideoDecoder(mime, msg);
+            err = setupVideoDecoder(mime, msg, haveNativeWindow);
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
         int32_t numChannels, sampleRate;
@@ -2053,7 +2062,8 @@
 status_t ACodec::setVideoPortFormatType(
         OMX_U32 portIndex,
         OMX_VIDEO_CODINGTYPE compressionFormat,
-        OMX_COLOR_FORMATTYPE colorFormat) {
+        OMX_COLOR_FORMATTYPE colorFormat,
+        bool usingNativeBuffers) {
     OMX_VIDEO_PARAM_PORTFORMATTYPE format;
     InitOMXParams(&format);
     format.nPortIndex = portIndex;
@@ -2073,10 +2083,10 @@
 
         // substitute back flexible color format to codec supported format
         OMX_U32 flexibleEquivalent;
-        if (compressionFormat == OMX_VIDEO_CodingUnused &&
-                isFlexibleColorFormat(
-                        mOMX, mNode, format.eColorFormat, &flexibleEquivalent) &&
-                colorFormat == flexibleEquivalent) {
+        if (compressionFormat == OMX_VIDEO_CodingUnused
+                && isFlexibleColorFormat(
+                        mOMX, mNode, format.eColorFormat, usingNativeBuffers, &flexibleEquivalent)
+                && colorFormat == flexibleEquivalent) {
             ALOGI("[%s] using color format %#x in place of %#x",
                     mComponentName.c_str(), format.eColorFormat, colorFormat);
             colorFormat = format.eColorFormat;
@@ -2120,18 +2130,66 @@
     return err;
 }
 
-status_t ACodec::setSupportedOutputFormat() {
-    OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+// Set optimal output format. OMX component lists output formats in the order
+// of preference, but this got more complicated since the introduction of flexible
+// YUV formats. We support a legacy behavior for applications that do not use
+// surface output, do not specify an output format, but expect a "usable" standard
+// OMX format. SW readable and standard formats must be flex-YUV.
+//
+// Suggested preference order:
+// - optimal format for texture rendering (mediaplayer behavior)
+// - optimal SW readable & texture renderable format (flex-YUV support)
+// - optimal SW readable non-renderable format (flex-YUV bytebuffer support)
+// - legacy "usable" standard formats
+//
+// For legacy support, we prefer a standard format, but will settle for a SW readable
+// flex-YUV format.
+status_t ACodec::setSupportedOutputFormat(bool getLegacyFlexibleFormat) {
+    OMX_VIDEO_PARAM_PORTFORMATTYPE format, legacyFormat;
     InitOMXParams(&format);
     format.nPortIndex = kPortIndexOutput;
-    format.nIndex = 0;
 
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoPortFormat,
-            &format, sizeof(format));
-    CHECK_EQ(err, (status_t)OK);
-    CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
+    InitOMXParams(&legacyFormat);
+    // this field will change when we find a suitable legacy format
+    legacyFormat.eColorFormat = OMX_COLOR_FormatUnused;
 
+    for (OMX_U32 index = 0; ; ++index) {
+        format.nIndex = index;
+        status_t err = mOMX->getParameter(
+                mNode, OMX_IndexParamVideoPortFormat,
+                &format, sizeof(format));
+        if (err != OK) {
+            // no more formats, pick legacy format if found
+            if (legacyFormat.eColorFormat != OMX_COLOR_FormatUnused) {
+                 memcpy(&format, &legacyFormat, sizeof(format));
+                 break;
+            }
+            return err;
+        }
+        if (format.eCompressionFormat != OMX_VIDEO_CodingUnused) {
+            return OMX_ErrorBadParameter;
+        }
+        if (!getLegacyFlexibleFormat) {
+            break;
+        }
+        // standard formats that were exposed to users before
+        if (format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedPlanar
+                || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+                || format.eColorFormat == OMX_COLOR_FormatYUV420PackedSemiPlanar
+                || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+            break;
+        }
+        // find best legacy non-standard format
+        OMX_U32 flexibleEquivalent;
+        if (legacyFormat.eColorFormat == OMX_COLOR_FormatUnused
+                && isFlexibleColorFormat(
+                        mOMX, mNode, format.eColorFormat, false /* usingNativeBuffers */,
+                        &flexibleEquivalent)
+                && flexibleEquivalent == OMX_COLOR_FormatYUV420Flexible) {
+            memcpy(&legacyFormat, &format, sizeof(format));
+        }
+    }
     return mOMX->setParameter(
             mNode, OMX_IndexParamVideoPortFormat,
             &format, sizeof(format));
@@ -2183,7 +2241,7 @@
 }
 
 status_t ACodec::setupVideoDecoder(
-        const char *mime, const sp<AMessage> &msg) {
+        const char *mime, const sp<AMessage> &msg, bool haveNativeWindow) {
     int32_t width, height;
     if (!msg->findInt32("width", &width)
             || !msg->findInt32("height", &height)) {
@@ -2209,22 +2267,31 @@
         OMX_COLOR_FORMATTYPE colorFormat =
             static_cast<OMX_COLOR_FORMATTYPE>(tmp);
         err = setVideoPortFormatType(
-                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat);
+                kPortIndexOutput, OMX_VIDEO_CodingUnused, colorFormat, haveNativeWindow);
         if (err != OK) {
             ALOGW("[%s] does not support color format %d",
                   mComponentName.c_str(), colorFormat);
-            err = setSupportedOutputFormat();
+            err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
         }
     } else {
-        err = setSupportedOutputFormat();
+        err = setSupportedOutputFormat(!haveNativeWindow /* getLegacyFlexibleFormat */);
     }
 
     if (err != OK) {
         return err;
     }
 
+    int32_t frameRateInt;
+    float frameRateFloat;
+    if (!msg->findFloat("frame-rate", &frameRateFloat)) {
+        if (!msg->findInt32("frame-rate", &frameRateInt)) {
+            frameRateInt = -1;
+        }
+        frameRateFloat = (float)frameRateInt;
+    }
+
     err = setVideoFormatOnPort(
-            kPortIndexInput, width, height, compressionFormat);
+            kPortIndexInput, width, height, compressionFormat, frameRateFloat);
 
     if (err != OK) {
         return err;
@@ -2988,7 +3055,8 @@
 
 status_t ACodec::setVideoFormatOnPort(
         OMX_U32 portIndex,
-        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
+        int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat,
+        float frameRate) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
     def.nPortIndex = portIndex;
@@ -3016,6 +3084,9 @@
     if (portIndex == kPortIndexInput) {
         video_def->eCompressionFormat = compressionFormat;
         video_def->eColorFormat = OMX_COLOR_FormatUnused;
+        if (frameRate >= 0) {
+            video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
+        }
     }
 
     err = mOMX->setParameter(
@@ -3217,7 +3288,7 @@
 // static
 bool ACodec::isFlexibleColorFormat(
          const sp<IOMX> &omx, IOMX::node_id node,
-         uint32_t colorFormat, OMX_U32 *flexibleEquivalent) {
+         uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
     DescribeColorFormatParams describeParams;
     InitOMXParams(&describeParams);
     describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
@@ -3226,6 +3297,7 @@
     describeParams.nFrameHeight = 128;
     describeParams.nStride = 128;
     describeParams.nSliceHeight = 128;
+    describeParams.bUsingNativeBuffers = (OMX_BOOL)usingNativeBuffers;
 
     CHECK(flexibleEquivalent != NULL);
 
@@ -3283,20 +3355,23 @@
                     notify->setInt32("slice-height", videoDef->nSliceHeight);
                     notify->setInt32("color-format", videoDef->eColorFormat);
 
-                    DescribeColorFormatParams describeParams;
-                    InitOMXParams(&describeParams);
-                    describeParams.eColorFormat = videoDef->eColorFormat;
-                    describeParams.nFrameWidth = videoDef->nFrameWidth;
-                    describeParams.nFrameHeight = videoDef->nFrameHeight;
-                    describeParams.nStride = videoDef->nStride;
-                    describeParams.nSliceHeight = videoDef->nSliceHeight;
+                    if (mNativeWindow == NULL) {
+                        DescribeColorFormatParams describeParams;
+                        InitOMXParams(&describeParams);
+                        describeParams.eColorFormat = videoDef->eColorFormat;
+                        describeParams.nFrameWidth = videoDef->nFrameWidth;
+                        describeParams.nFrameHeight = videoDef->nFrameHeight;
+                        describeParams.nStride = videoDef->nStride;
+                        describeParams.nSliceHeight = videoDef->nSliceHeight;
+                        describeParams.bUsingNativeBuffers = OMX_FALSE;
 
-                    if (describeColorFormat(mOMX, mNode, describeParams)) {
-                        notify->setBuffer(
-                                "image-data",
-                                ABuffer::CreateAsCopy(
-                                        &describeParams.sMediaImage,
-                                        sizeof(describeParams.sMediaImage)));
+                        if (describeColorFormat(mOMX, mNode, describeParams)) {
+                            notify->setBuffer(
+                                    "image-data",
+                                    ABuffer::CreateAsCopy(
+                                            &describeParams.sMediaImage,
+                                            sizeof(describeParams.sMediaImage)));
+                        }
                     }
 
                     if (portIndex != kPortIndexOutput) {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 007c090..87eef1e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -889,10 +889,7 @@
         }
     }
     if ((mFlags & LOOPING)
-            || ((mFlags & AUTO_LOOPING)
-                && (mAudioSink == NULL || mAudioSink->realtime()))) {
-        // Don't AUTO_LOOP if we're being recorded, since that cannot be
-        // turned off and recording would go on indefinitely.
+            || (mFlags & AUTO_LOOPING)) {
 
         seekTo_l(0);
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index dec52f3..8bf7f63 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1144,7 +1144,7 @@
         {
             *offset += chunk_size;
 
-            if (chunk_data_size < 4) {
+            if (chunk_data_size < 4 || mLastTrack == NULL) {
                 return ERROR_MALFORMED;
             }
 
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 8fa07b2..c838427 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1716,7 +1716,7 @@
     size_t i = 0;
     for (;;) {
         sp<ABuffer> csd;
-        if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
+        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
             break;
         }
 
@@ -2239,7 +2239,7 @@
             memcpy(csd->data() + 4, nalStart, nalSize);
 
             mOutputFormat->setBuffer(
-                    StringPrintf("csd-%u", csdIndex).c_str(), csd);
+                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
 
             ++csdIndex;
         }
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index bd0a41d..7d7d631 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -354,7 +354,7 @@
     Mutex::Autolock autoLock(mLock);
 
     if (n == 0 || mDisconnecting) {
-        ALOGI("ERROR_END_OF_STREAM");
+        ALOGI("caching reached eos.");
 
         mNumRetriesLeft = 0;
         mFinalStatus = ERROR_END_OF_STREAM;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 69f4989..ea19ab2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -4538,7 +4538,8 @@
 
             OMX_U32 flexibleEquivalent;
             if (ACodec::isFlexibleColorFormat(
-                        omx, node, portFormat.eColorFormat, &flexibleEquivalent)) {
+                        omx, node, portFormat.eColorFormat, false /* usingNativeWindow */,
+                        &flexibleEquivalent)) {
                 bool marked = false;
                 for (size_t i = 0; i < caps->mColorFormats.size(); i++) {
                     if (caps->mColorFormats.itemAt(i) == flexibleEquivalent) {
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
index d1fe833..4fd16a1 100644
--- a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
@@ -245,10 +245,9 @@
 Word32 rsqrt(Word32 value,     /*!< Operand to square root (0.0 ... 1) */
              Word32 accuracy)  /*!< Number of valid bits that will be calculated */
 {
-    UNUSED(accuracy);
-
     Word32 root = 0;
 	Word32 scale;
+    UNUSED(accuracy);
 
 	if(value < 0)
 		return 0;
diff --git a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp b/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
index 521fe2b..41a9e98 100644
--- a/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/test/amrnbdec_test.cpp
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 
+#include <malloc.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
index b783222..90d7c6b 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -292,8 +292,10 @@
 
     if (video->shortVideoHeader == PV_TRUE)
     {
-        video->displayWidth = video->width = width;
-        video->displayHeight = video->height = height;
+        video->displayWidth = width;
+        video->displayHeight = height;
+        video->width = (width + 15) & -16;
+        video->height = (height + 15) & -16;
 
         video->nMBPerRow =
             video->nMBinGOB  = video->width / MB_SIZE;
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index b03ec8c..60c79a6 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -118,6 +118,10 @@
         {
             /* support SPL0-3 & SSPL0-2   */
             if (tmpvar != 0x01 && tmpvar != 0x02 && tmpvar != 0x03 && tmpvar != 0x08 &&
+                    /* While not technically supported, try to decode SPL4&SPL5 files as well. */
+                    /* We'll fail later if the size is too large.  This is to allow playback of */
+                    /* some <=CIF files generated by other encoders. */
+                    tmpvar != 0x04 && tmpvar != 0x05 &&
                     tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 &&
                     tmpvar != 0x21 && tmpvar != 0x22 &&  /* Core Profile Levels */
                     tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3 &&
diff --git a/media/libstagefright/codecs/on2/enc/Android.mk b/media/libstagefright/codecs/on2/enc/Android.mk
index e265104..253fa04 100644
--- a/media/libstagefright/codecs/on2/enc/Android.mk
+++ b/media/libstagefright/codecs/on2/enc/Android.mk
@@ -6,7 +6,6 @@
 
 LOCAL_C_INCLUDES := \
         $(TOP)/external/libvpx/libvpx \
-        $(TOP)/external/openssl/include \
         $(TOP)/external/libvpx/libvpx/vpx_codec \
         $(TOP)/external/libvpx/libvpx/vpx_ports \
         frameworks/av/media/libstagefright/include \
diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
index 524a3f0..a073dcb 100644
--- a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
+++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
@@ -36,6 +36,7 @@
     1. Include headers
 ------------------------------------------------------------------------------*/
 #include <stdlib.h>
+#include <string.h>
 #include "basetype.h"
 #include "h264bsd_container.h"
 #include "H264SwDecApi.h"
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 795e8a6..1f46bc9 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -426,19 +426,19 @@
 
     AString tmp;
     if (isFourcc(mWhat)) {
-        tmp = StringPrintf(
+        tmp = AStringPrintf(
                 "'%c%c%c%c'",
                 (char)(mWhat >> 24),
                 (char)((mWhat >> 16) & 0xff),
                 (char)((mWhat >> 8) & 0xff),
                 (char)(mWhat & 0xff));
     } else {
-        tmp = StringPrintf("0x%08x", mWhat);
+        tmp = AStringPrintf("0x%08x", mWhat);
     }
     s.append(tmp);
 
     if (mTarget != 0) {
-        tmp = StringPrintf(", target = %d", mTarget);
+        tmp = AStringPrintf(", target = %d", mTarget);
         s.append(tmp);
     }
     s.append(") = {\n");
@@ -448,37 +448,37 @@
 
         switch (item.mType) {
             case kTypeInt32:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "int32_t %s = %d", item.mName, item.u.int32Value);
                 break;
             case kTypeInt64:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "int64_t %s = %lld", item.mName, item.u.int64Value);
                 break;
             case kTypeSize:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "size_t %s = %d", item.mName, item.u.sizeValue);
                 break;
             case kTypeFloat:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "float %s = %f", item.mName, item.u.floatValue);
                 break;
             case kTypeDouble:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "double %s = %f", item.mName, item.u.doubleValue);
                 break;
             case kTypePointer:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "void *%s = %p", item.mName, item.u.ptrValue);
                 break;
             case kTypeString:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "string %s = \"%s\"",
                         item.mName,
                         item.u.stringValue->c_str());
                 break;
             case kTypeObject:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "RefBase *%s = %p", item.mName, item.u.refValue);
                 break;
             case kTypeBuffer:
@@ -486,18 +486,18 @@
                 sp<ABuffer> buffer = static_cast<ABuffer *>(item.u.refValue);
 
                 if (buffer != NULL && buffer->data() != NULL && buffer->size() <= 64) {
-                    tmp = StringPrintf("Buffer %s = {\n", item.mName);
+                    tmp = AStringPrintf("Buffer %s = {\n", item.mName);
                     hexdump(buffer->data(), buffer->size(), indent + 4, &tmp);
                     appendIndent(&tmp, indent + 2);
                     tmp.append("}");
                 } else {
-                    tmp = StringPrintf(
+                    tmp = AStringPrintf(
                             "Buffer *%s = %p", item.mName, buffer.get());
                 }
                 break;
             }
             case kTypeMessage:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "AMessage %s = %s",
                         item.mName,
                         static_cast<AMessage *>(
@@ -505,7 +505,7 @@
                                 indent + strlen(item.mName) + 14).c_str());
                 break;
             case kTypeRect:
-                tmp = StringPrintf(
+                tmp = AStringPrintf(
                         "Rect %s(%d, %d, %d, %d)",
                         item.mName,
                         item.u.rectValue.mLeft,
diff --git a/media/libstagefright/foundation/ANetworkSession.cpp b/media/libstagefright/foundation/ANetworkSession.cpp
index 4504c2b..b230400 100644
--- a/media/libstagefright/foundation/ANetworkSession.cpp
+++ b/media/libstagefright/foundation/ANetworkSession.cpp
@@ -187,7 +187,7 @@
         CHECK_GE(res, 0);
 
         in_addr_t addr = ntohl(localAddr.sin_addr.s_addr);
-        AString localAddrString = StringPrintf(
+        AString localAddrString = AStringPrintf(
                 "%d.%d.%d.%d",
                 (addr >> 24),
                 (addr >> 16) & 0xff,
@@ -195,7 +195,7 @@
                 addr & 0xff);
 
         addr = ntohl(remoteAddr.sin_addr.s_addr);
-        AString remoteAddrString = StringPrintf(
+        AString remoteAddrString = AStringPrintf(
                 "%d.%d.%d.%d",
                 (addr >> 24),
                 (addr >> 16) & 0xff,
@@ -301,7 +301,7 @@
                 uint32_t ip = ntohl(remoteAddr.sin_addr.s_addr);
                 notify->setString(
                         "fromAddr",
-                        StringPrintf(
+                        AStringPrintf(
                             "%u.%u.%u.%u",
                             ip >> 24,
                             (ip >> 16) & 0xff,
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
index 9835ca3..b167543 100644
--- a/media/libstagefright/foundation/AString.cpp
+++ b/media/libstagefright/foundation/AString.cpp
@@ -366,7 +366,7 @@
     return err;
 }
 
-AString StringPrintf(const char *format, ...) {
+AString AStringPrintf(const char *format, ...) {
     va_list ap;
     va_start(ap, format);
 
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
index e8d558c..93b7935 100644
--- a/media/libstagefright/httplive/Android.mk
+++ b/media/libstagefright/httplive/Android.mk
@@ -10,8 +10,7 @@
 
 LOCAL_C_INCLUDES:= \
 	$(TOP)/frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax \
-	$(TOP)/external/openssl/include
+	$(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_CFLAGS += -Werror
 
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 190188a..d0f3bc2 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -846,11 +846,11 @@
                 headers.add(
                         String8("Range"),
                         String8(
-                            StringPrintf(
+                            AStringPrintf(
                                 "bytes=%lld-%s",
                                 range_offset,
                                 range_length < 0
-                                    ? "" : StringPrintf("%lld",
+                                    ? "" : AStringPrintf("%lld",
                                             range_offset + range_length - 1).c_str()).c_str()));
             }
             status_t err = mHTTPDataSource->connect(url, &headers);
@@ -1508,14 +1508,15 @@
 
                     if (meta != NULL && !meta->findInt32("discontinuity", &type)) {
                         int64_t tmpUs;
-                        CHECK(meta->findInt64("timeUs", &tmpUs));
-                        if (startTimeUs < 0 || tmpUs < startTimeUs) {
-                            startTimeUs = tmpUs;
-                        }
+                        int64_t tmpSegmentUs;
 
-                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpUs));
-                        if (segmentStartTimeUs < 0 || tmpUs < segmentStartTimeUs) {
-                            segmentStartTimeUs = tmpUs;
+                        CHECK(meta->findInt64("timeUs", &tmpUs));
+                        CHECK(meta->findInt64("segmentStartTimeUs", &tmpSegmentUs));
+                        if (startTimeUs < 0 || tmpSegmentUs < segmentStartTimeUs) {
+                            startTimeUs = tmpUs;
+                            segmentStartTimeUs = tmpSegmentUs;
+                        } else if (tmpSegmentUs == segmentStartTimeUs && tmpUs < startTimeUs) {
+                            startTimeUs = tmpUs;
                         }
 
                         int32_t seq;
@@ -1627,6 +1628,12 @@
         return;
     }
 
+    if (mSwitchInProgress || mReconfigurationInProgress) {
+        ALOGV("Switch/Reconfig in progress, defer switch down");
+        mSwitchDownMonitor->post(1000000ll);
+        return;
+    }
+
     for (size_t i = 0; i < kMaxStreams; ++i) {
         int32_t targetDuration;
         sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(indexToType(i));
@@ -1657,7 +1664,6 @@
         return;
     }
 
-    changeConfiguration(-1, mCurBandwidthIndex - 1, false);
 }
 
 // Mark switch done when:
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 1526af1..1227600 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -757,6 +757,9 @@
                     mSeqNumber = firstSeqNumberInPlaylist;
                 }
             } else {
+                // When seeking mSegmentStartTimeUs is unavailable (< 0), we
+                // use mStartTimeUs (client supplied timestamp) to determine both start segment
+                // and relative position inside a segment
                 mSeqNumber = getSeqNumberForTime(mStartTimeUs);
                 mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber);
             }
@@ -765,6 +768,10 @@
                     mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
                     lastSeqNumberInPlaylist);
         } else {
+            // When adapting or track switching, mSegmentStartTimeUs (relative
+            // to media time 0) is used to determine the start segment; mStartTimeUs (absolute
+            // timestamps coming from the media container) is used to determine the position
+            // inside a segments.
             mSeqNumber = getSeqNumberForTime(mSegmentStartTimeUs);
             if (mAdaptive) {
                 // avoid double fetch/decode
@@ -976,6 +983,10 @@
         if (err == -EAGAIN) {
             // starting sequence number too low/high
             mTSParser.clear();
+            for (size_t i = 0; i < mPacketSources.size(); i++) {
+                sp<AnotherPacketSource> packetSource = mPacketSources.valueAt(i);
+                packetSource->clear();
+            }
             postMonitorQueue();
             return;
         } else if (err == ERROR_OUT_OF_RANGE) {
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 793d116..e1607bf 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -461,7 +461,7 @@
         sdp.append("m=audio ");
     }
 
-    sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port)));
+    sdp.append(AStringPrintf("%d", ntohs(mRTPAddr.sin_port)));
     sdp.append(
           " RTP/AVP " PT_STR "\r\n"
           "b=AS 320000\r\n"
@@ -480,7 +480,7 @@
         CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000);
 
         sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB");
-        sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels));
+        sdp.append(AStringPrintf("/%d/%d", sampleRate, numChannels));
     } else {
         TRESPASS();
     }
@@ -543,7 +543,7 @@
     CHECK_EQ((unsigned)data[0], 0x67u);
 
     mProfileLevel =
-        StringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
+        AStringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
 
     encodeBase64(data, startCodePos, &mSeqParamSet);
 
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index f25539c..60b3aaf 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -42,7 +42,7 @@
 
 // static
 const AString ARTSPConnection::sUserAgent =
-    StringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
+    AStringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
 
 ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
     : mUIDValid(uidValid),
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index d60dc2f..9fedb71 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -19,10 +19,11 @@
         ASessionDescription.cpp     \
         SDPLoader.cpp               \
 
+LOCAL_SHARED_LIBRARIES += libcrypto
+
 LOCAL_C_INCLUDES:= \
 	$(TOP)/frameworks/av/media/libstagefright \
-	$(TOP)/frameworks/native/include/media/openmax \
-	$(TOP)/external/openssl/include
+	$(TOP)/frameworks/native/include/media/openmax
 
 LOCAL_MODULE:= libstagefright_rtsp
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 423a420..3bf489b 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -156,7 +156,7 @@
             mSessionURL.append("rtsp://");
             mSessionURL.append(host);
             mSessionURL.append(":");
-            mSessionURL.append(StringPrintf("%u", port));
+            mSessionURL.append(AStringPrintf("%u", port));
             mSessionURL.append(path);
 
             ALOGV("rewritten session url: '%s'", mSessionURL.c_str());
@@ -508,7 +508,7 @@
                             mSessionURL.append("rtsp://");
                             mSessionURL.append(host);
                             mSessionURL.append(":");
-                            mSessionURL.append(StringPrintf("%u", port));
+                            mSessionURL.append(AStringPrintf("%u", port));
                             mSessionURL.append(path);
 
                             ALOGI("rewritten session url: '%s'", mSessionURL.c_str());
@@ -1238,7 +1238,7 @@
                 request.append("\r\n");
 
                 request.append(
-                        StringPrintf(
+                        AStringPrintf(
                             "Range: npt=%lld-\r\n", timeUs / 1000000ll));
 
                 request.append("\r\n");
diff --git a/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp b/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
index 40e93c7..3a06d61 100644
--- a/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextSRTSource_test.cpp
@@ -120,26 +120,26 @@
         err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
         EXPECT_EQ(OK, err);
         CheckStartTimeMs(parcel, i * kSecToMsec);
-        subtitle = StringPrintf("%d\n\n", i);
+        subtitle = AStringPrintf("%d\n\n", i);
         CheckDataEquals(parcel, subtitle.c_str());
     }
     // read edge cases
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
     EXPECT_EQ(OK, err);
     CheckStartTimeMs(parcel, 5500);
-    subtitle = StringPrintf("6\n\n");
+    subtitle = AStringPrintf("6\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
     EXPECT_EQ(OK, err);
     CheckStartTimeMs(parcel, 5800);
-    subtitle = StringPrintf("7\n\n");
+    subtitle = AStringPrintf("7\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
     EXPECT_EQ(OK, err);
     CheckStartTimeMs(parcel, 6000);
-    subtitle = StringPrintf("8\n\n");
+    subtitle = AStringPrintf("8\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel);
@@ -202,21 +202,21 @@
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
     EXPECT_EQ(OK, err);
     EXPECT_EQ(5500 * kMsecToUsec, startTimeUs);
-    subtitle = StringPrintf("6\n\n");
+    subtitle = AStringPrintf("6\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     options.setSeekTo(5800 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
     EXPECT_EQ(OK, err);
     EXPECT_EQ(5800 * kMsecToUsec, startTimeUs);
-    subtitle = StringPrintf("7\n\n");
+    subtitle = AStringPrintf("7\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 
     options.setSeekTo(6000 * kMsecToUsec, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
     err = mSource->read(&startTimeUs, &endTimeUs, &parcel, &options);
     EXPECT_EQ(OK, err);
     EXPECT_EQ(6000 * kMsecToUsec, startTimeUs);
-    subtitle = StringPrintf("8\n\n");
+    subtitle = AStringPrintf("8\n\n");
     CheckDataEquals(parcel, subtitle.c_str());
 }
 
diff --git a/media/libstagefright/wifi-display/VideoFormats.cpp b/media/libstagefright/wifi-display/VideoFormats.cpp
index 04e02c1..2f4af5b 100644
--- a/media/libstagefright/wifi-display/VideoFormats.cpp
+++ b/media/libstagefright/wifi-display/VideoFormats.cpp
@@ -435,7 +435,7 @@
     //   max-hres (none or 2 byte)
     //   max-vres (none or 2 byte)
 
-    return StringPrintf(
+    return AStringPrintf(
             "%02x 00 %02x %02x %08x %08x %08x 00 0000 0000 00 none none",
             forM4Message ? 0x00 : ((mNativeIndex << 3) | mNativeType),
             mConfigs[mNativeType][mNativeIndex].profile,
diff --git a/media/libstagefright/wifi-display/source/TSPacketizer.cpp b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
index 50d317a..4c5ad17 100644
--- a/media/libstagefright/wifi-display/source/TSPacketizer.cpp
+++ b/media/libstagefright/wifi-display/source/TSPacketizer.cpp
@@ -106,7 +106,7 @@
             || !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
         for (size_t i = 0;; ++i) {
             sp<ABuffer> csd;
-            if (!mFormat->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) {
+            if (!mFormat->findBuffer(AStringPrintf("csd-%d", i).c_str(), &csd)) {
                 break;
             }
 
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 0c39ccf..7eb8b73 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -598,7 +598,7 @@
     AppendCommonResponse(&request, mNextCSeq);
 
     request.append("Content-Type: text/parameters\r\n");
-    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
     request.append("\r\n");
     request.append(body);
 
@@ -639,26 +639,26 @@
 
     if (mSinkSupportsAudio) {
         body.append(
-                StringPrintf("wfd_audio_codecs: %s\r\n",
+                AStringPrintf("wfd_audio_codecs: %s\r\n",
                              (mUsingPCMAudio
                                 ? "LPCM 00000002 00" // 2 ch PCM 48kHz
                                 : "AAC 00000001 00")));  // 2 ch AAC 48kHz
     }
 
     body.append(
-            StringPrintf(
+            AStringPrintf(
                 "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n",
                 mClientInfo.mLocalIP.c_str()));
 
     body.append(
-            StringPrintf(
+            AStringPrintf(
                 "wfd_client_rtp_ports: %s\r\n", mWfdClientRtpPorts.c_str()));
 
     AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
     AppendCommonResponse(&request, mNextCSeq);
 
     request.append("Content-Type: text/parameters\r\n");
-    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
     request.append("\r\n");
     request.append(body);
 
@@ -704,7 +704,7 @@
     AppendCommonResponse(&request, mNextCSeq);
 
     request.append("Content-Type: text/parameters\r\n");
-    request.append(StringPrintf("Content-Length: %d\r\n", body.size()));
+    request.append(AStringPrintf("Content-Length: %d\r\n", body.size()));
     request.append("\r\n");
     request.append(body);
 
@@ -729,7 +729,7 @@
 
     CHECK_EQ(sessionID, mClientSessionID);
     request.append(
-            StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
+            AStringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID));
     request.append("\r\n");  // Empty body
 
     status_t err =
@@ -1305,7 +1305,7 @@
 
     if (rtpMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
         response.append(
-                StringPrintf(
+                AStringPrintf(
                     "Transport: RTP/AVP/TCP;interleaved=%d-%d;",
                     clientRtp, clientRtcp));
     } else {
@@ -1318,14 +1318,14 @@
 
         if (clientRtcp >= 0) {
             response.append(
-                    StringPrintf(
+                    AStringPrintf(
                         "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;"
                         "server_port=%d-%d\r\n",
                         transportString.c_str(),
                         clientRtp, clientRtcp, serverRtp, serverRtp + 1));
         } else {
             response.append(
-                    StringPrintf(
+                    AStringPrintf(
                         "Transport: RTP/AVP/%s;unicast;client_port=%d;"
                         "server_port=%d\r\n",
                         transportString.c_str(),
@@ -1585,15 +1585,15 @@
     response->append(buf);
     response->append("\r\n");
 
-    response->append(StringPrintf("Server: %s\r\n", sUserAgent.c_str()));
+    response->append(AStringPrintf("Server: %s\r\n", sUserAgent.c_str()));
 
     if (cseq >= 0) {
-        response->append(StringPrintf("CSeq: %d\r\n", cseq));
+        response->append(AStringPrintf("CSeq: %d\r\n", cseq));
     }
 
     if (playbackSessionID >= 0ll) {
         response->append(
-                StringPrintf(
+                AStringPrintf(
                     "Session: %d;timeout=%lld\r\n",
                     playbackSessionID, kPlaybackSessionTimeoutSecs));
     }
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index e4e16f2..07199e3 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -1119,10 +1119,10 @@
 MtpResponseCode MtpServer::doDeleteObject() {
     if (!hasStorage())
         return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
-    if (mRequest.getParameterCount() < 2)
+    if (mRequest.getParameterCount() < 1)
         return MTP_RESPONSE_INVALID_PARAMETER;
     MtpObjectHandle handle = mRequest.getParameter(1);
-    MtpObjectFormat format = mRequest.getParameter(2);
+    MtpObjectFormat format;
     // FIXME - support deleting all objects if handle is 0xFFFFFFFF
     // FIXME - implement deleting objects by format
 
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 4508fa7..116d0d6 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -75,7 +75,8 @@
     // indicate a change in device connection status
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
-                                          const char *device_address) = 0;
+                                              const char *device_address,
+                                              const char *device_name) = 0;
     // retrieve a device connection status
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                           const char *device_address) = 0;
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index a45dbb3..e9ff8389 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -28,7 +28,8 @@
 
 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                   audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                  const char *device_address,
+                                                  const char *device_name)
 {
     if (mAudioPolicyManager == NULL) {
         return NO_INIT;
@@ -46,8 +47,8 @@
 
     ALOGV("setDeviceConnectionState()");
     Mutex::Autolock _l(mLock);
-    return mAudioPolicyManager->setDeviceConnectionState(device,
-                                                      state, device_address);
+    return mAudioPolicyManager->setDeviceConnectionState(device, state,
+                                                         device_address, device_name);
 }
 
 audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index b8846c6..5a91192 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -33,7 +33,8 @@
 
 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                   audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                  const char *device_address,
+                                                  const char *device_name __unused)
 {
     if (mpAudioPolicy == NULL) {
         return NO_INIT;
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 0349327..5a0c958 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -212,34 +212,32 @@
 // ----------------------------------------------------------------------------
 
 status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
-                                                          audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                      audio_policy_dev_state_t state,
+                                                      const char *device_address,
+                                                      const char *device_name)
 {
-    return setDeviceConnectionStateInt(device, state, device_address);
+    return setDeviceConnectionStateInt(device, state, device_address, device_name);
 }
 
 status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
-                                                          audio_policy_dev_state_t state,
-                                                  const char *device_address)
+                                                         audio_policy_dev_state_t state,
+                                                         const char *device_address,
+                                                         const char *device_name)
 {
-    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
-    // handle legacy remote submix case where the address was not always specified
-    if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
-        address = String8("0");
-    }
-
-    ALOGV("setDeviceConnectionState() device: %x, state %d, address %s",
-            device, state, address.string());
+    ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s",
+-            device, state, device_address, device_name);
 
     // connect/disconnect only 1 device at a time
     if (!audio_is_output_device(device) && !audio_is_input_device(device)) return BAD_VALUE;
 
+    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address);
+
+    String8 name = String8(device_name != NULL ? device_name : "");
+
     // handle output devices
     if (audio_is_output_device(device)) {
         SortedVector <audio_io_handle_t> outputs;
 
-        sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
-        devDesc->mAddress = address;
         ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
 
         // save a copy of the opened output descriptors before any output is opened or closed
@@ -248,7 +246,7 @@
         switch (state)
         {
         // handle output device connection
-        case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
+        case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
             if (index >= 0) {
                 ALOGW("setDeviceConnectionState() device already connected: %x", device);
                 return INVALID_OPERATION;
@@ -265,13 +263,12 @@
                     mAvailableOutputDevices.remove(devDesc);
                     return INVALID_OPERATION;
                 }
-                mAvailableOutputDevices[index]->mId = nextUniqueId();
-                mAvailableOutputDevices[index]->mModule = module;
+                mAvailableOutputDevices[index]->attach(module);
             } else {
                 return NO_MEMORY;
             }
 
-            if (checkOutputsForDevice(devDesc, state, outputs, address) != NO_ERROR) {
+            if (checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress) != NO_ERROR) {
                 mAvailableOutputDevices.remove(devDesc);
                 return INVALID_OPERATION;
             }
@@ -280,7 +277,14 @@
                     "checkOutputsForDevice() returned no outputs but status OK");
             ALOGV("setDeviceConnectionState() checkOutputsForDevice() returned %zu outputs",
                   outputs.size());
-            break;
+
+
+            // Set connect to HALs
+            AudioParameter param = AudioParameter(devDesc->mAddress);
+            param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
+            mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+
+            } break;
         // handle output device disconnection
         case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
             if (index < 0) {
@@ -290,15 +294,15 @@
 
             ALOGV("setDeviceConnectionState() disconnecting output device %x", device);
 
-            // Set Disconnect to HALs
-            AudioParameter param = AudioParameter(address);
+            // Send Disconnect to HALs
+            AudioParameter param = AudioParameter(devDesc->mAddress);
             param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device);
             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 
             // remove device from available output devices
             mAvailableOutputDevices.remove(devDesc);
 
-            checkOutputsForDevice(devDesc, state, outputs, address);
+            checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
             } break;
 
         default:
@@ -355,8 +359,6 @@
     if (audio_is_input_device(device)) {
         SortedVector <audio_io_handle_t> inputs;
 
-        sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
-        devDesc->mAddress = address;
         ssize_t index = mAvailableInputDevices.indexOf(devDesc);
         switch (state)
         {
@@ -372,17 +374,22 @@
                       device);
                 return INVALID_OPERATION;
             }
-            if (checkInputsForDevice(device, state, inputs, address) != NO_ERROR) {
+            if (checkInputsForDevice(device, state, inputs, devDesc->mAddress) != NO_ERROR) {
                 return INVALID_OPERATION;
             }
 
             index = mAvailableInputDevices.add(devDesc);
             if (index >= 0) {
-                mAvailableInputDevices[index]->mId = nextUniqueId();
-                mAvailableInputDevices[index]->mModule = module;
+                mAvailableInputDevices[index]->attach(module);
             } else {
                 return NO_MEMORY;
             }
+
+            // Set connect to HALs
+            AudioParameter param = AudioParameter(devDesc->mAddress);
+            param.addInt(String8(AUDIO_PARAMETER_DEVICE_CONNECT), device);
+            mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
+
         } break;
 
         // handle input device disconnection
@@ -395,11 +402,11 @@
             ALOGV("setDeviceConnectionState() disconnecting input device %x", device);
 
             // Set Disconnect to HALs
-            AudioParameter param = AudioParameter(address);
+            AudioParameter param = AudioParameter(devDesc->mAddress);
             param.addInt(String8(AUDIO_PARAMETER_DEVICE_DISCONNECT), device);
             mpClientInterface->setParameters(AUDIO_IO_HANDLE_NONE, param.toString());
 
-            checkInputsForDevice(device, state, inputs, address);
+            checkInputsForDevice(device, state, inputs, devDesc->mAddress);
             mAvailableInputDevices.remove(devDesc);
 
         } break;
@@ -427,14 +434,7 @@
 audio_policy_dev_state_t AudioPolicyManager::getDeviceConnectionState(audio_devices_t device,
                                                   const char *device_address)
 {
-    audio_policy_dev_state_t state = AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
-    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
-    devDesc->mAddress = (device_address == NULL) ? String8("") : String8(device_address);
-    // handle legacy remote submix case where the address was not always specified
-    if (deviceDistinguishesOnAddress(device) && (devDesc->mAddress.length() == 0)) {
-        devDesc->mAddress = String8("0");
-    }
-    ssize_t index;
+    sp<DeviceDescriptor> devDesc = getDeviceDescriptor(device, device_address);
     DeviceVector *deviceVector;
 
     if (audio_is_output_device(device)) {
@@ -446,7 +446,7 @@
         return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
     }
 
-    index = deviceVector->indexOf(devDesc);
+    ssize_t index = deviceVector->indexOf(devDesc);
     if (index >= 0) {
         return AUDIO_POLICY_DEVICE_STATE_AVAILABLE;
     } else {
@@ -454,6 +454,36 @@
     }
 }
 
+sp<AudioPolicyManager::DeviceDescriptor>  AudioPolicyManager::getDeviceDescriptor(
+                                                                    const audio_devices_t device,
+                                                                    const char *device_address)
+{
+    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
+    // handle legacy remote submix case where the address was not always specified
+    if (deviceDistinguishesOnAddress(device) && (address.length() == 0)) {
+        address = String8("0");
+    }
+
+    for (size_t i = 0; i < mHwModules.size(); i++) {
+        if (mHwModules[i]->mHandle == 0) {
+            continue;
+        }
+        DeviceVector deviceList =
+                mHwModules[i]->mDeclaredDevices.getDevicesFromTypeAddr(device, address);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+        deviceList = mHwModules[i]->mDeclaredDevices.getDevicesFromType(device);
+        if (!deviceList.isEmpty()) {
+            return deviceList.itemAt(0);
+        }
+    }
+
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
+    devDesc->mAddress = address;
+    return devDesc;
+}
+
 void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs)
 {
     bool createTxPatch = false;
@@ -1098,6 +1128,10 @@
             if (output != AUDIO_IO_HANDLE_NONE) {
                 mpClientInterface->closeOutput(output);
             }
+            // fall back to mixer output if possible when the direct output could not be open
+            if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) {
+                goto non_direct_output;
+            }
             return AUDIO_IO_HANDLE_NONE;
         }
         outputDesc->mSamplingRate = config.sample_rate;
@@ -1290,7 +1324,8 @@
                 outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                         AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                        outputDesc->mPolicyMix->mRegistrationId);
+                        outputDesc->mPolicyMix->mRegistrationId,
+                        "remote-submix");
         }
 
         // force reevaluating accessibility routing when ringtone or alarm starts
@@ -1339,7 +1374,8 @@
                     outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                         AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                        outputDesc->mPolicyMix->mRegistrationId);
+                        outputDesc->mPolicyMix->mRegistrationId,
+                        "remote-submix");
             }
 
             outputDesc->mStopTime[stream] = systemTime();
@@ -1640,7 +1676,7 @@
             if (address != "") {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                         AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                        address);
+                        address, "remote-submix");
             }
         }
     }
@@ -1688,7 +1724,7 @@
             if (address != "") {
                 setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                                          AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                         address);
+                                         address, "remote-submix");
             }
         }
 
@@ -2145,11 +2181,11 @@
         if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                      AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                                     address.string());
+                                     address.string(), "remote-submix");
         } else {
             setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                                      AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
-                                     address.string());
+                                     address.string(), "remote-submix");
         }
     }
     return NO_ERROR;
@@ -2187,7 +2223,7 @@
         {
             setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                                      AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                     address.string());
+                                     address.string(), "remote-submix");
         }
 
         if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
@@ -2195,7 +2231,7 @@
         {
             setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                                      AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
-                                     address.string());
+                                     address.string(), "remote-submix");
         }
         module->removeOutputProfile(address);
         module->removeInputProfile(address);
@@ -3010,6 +3046,8 @@
     return android_atomic_inc(&mAudioPortGeneration);
 }
 
+int32_t volatile AudioPolicyManager::mNextUniqueId = 1;
+
 AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
     :
 #ifdef AUDIO_POLICY_TEST
@@ -3020,7 +3058,7 @@
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
     mA2dpSuspended(false),
-    mSpeakerDrcEnabled(false), mNextUniqueId(1),
+    mSpeakerDrcEnabled(false),
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
@@ -3033,7 +3071,7 @@
         mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
     }
 
-    mDefaultOutputDevice = new DeviceDescriptor(String8(""), AUDIO_DEVICE_OUT_SPEAKER);
+    mDefaultOutputDevice = new DeviceDescriptor(String8("Speaker"), AUDIO_DEVICE_OUT_SPEAKER);
     if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
         if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
             ALOGE("could not load audio policy configuration file, setting defaults");
@@ -3116,9 +3154,8 @@
                     ssize_t index =
                             mAvailableOutputDevices.indexOf(outProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
-                    if ((index >= 0) && (mAvailableOutputDevices[index]->mId == 0)) {
-                        mAvailableOutputDevices[index]->mId = nextUniqueId();
-                        mAvailableOutputDevices[index]->mModule = mHwModules[i];
+                    if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
+                        mAvailableOutputDevices[index]->attach(mHwModules[i]);
                     }
                 }
                 if (mPrimaryOutput == 0 &&
@@ -3185,9 +3222,8 @@
                     ssize_t index =
                             mAvailableInputDevices.indexOf(inProfile->mSupportedDevices[k]);
                     // give a valid ID to an attached device once confirmed it is reachable
-                    if ((index >= 0) && (mAvailableInputDevices[index]->mId == 0)) {
-                        mAvailableInputDevices[index]->mId = nextUniqueId();
-                        mAvailableInputDevices[index]->mModule = mHwModules[i];
+                    if (index >= 0 && !mAvailableInputDevices[index]->isAttached()) {
+                        mAvailableInputDevices[index]->attach(mHwModules[i]);
                     }
                 }
                 mpClientInterface->closeInput(input);
@@ -3200,7 +3236,7 @@
     }
     // make sure all attached devices have been allocated a unique ID
     for (size_t i = 0; i  < mAvailableOutputDevices.size();) {
-        if (mAvailableOutputDevices[i]->mId == 0) {
+        if (!mAvailableOutputDevices[i]->isAttached()) {
             ALOGW("Input device %08x unreachable", mAvailableOutputDevices[i]->mDeviceType);
             mAvailableOutputDevices.remove(mAvailableOutputDevices[i]);
             continue;
@@ -3208,7 +3244,7 @@
         i++;
     }
     for (size_t i = 0; i  < mAvailableInputDevices.size();) {
-        if (mAvailableInputDevices[i]->mId == 0) {
+        if (!mAvailableInputDevices[i]->isAttached()) {
             ALOGW("Input device %08x unreachable", mAvailableInputDevices[i]->mDeviceType);
             mAvailableInputDevices.remove(mAvailableInputDevices[i]);
             continue;
@@ -6377,7 +6413,7 @@
     profile->mChannelMasks.add(config->channel_mask);
     profile->mFormats.add(config->format);
 
-    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
     devDesc->mAddress = address;
     profile->mSupportedDevices.add(devDesc);
 
@@ -6407,7 +6443,7 @@
     profile->mChannelMasks.add(config->channel_mask);
     profile->mFormats.add(config->format);
 
-    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(String8(""), device);
+    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(name, device);
     devDesc->mAddress = address;
     profile->mSupportedDevices.add(devDesc);
 
@@ -6473,16 +6509,22 @@
 
 AudioPolicyManager::AudioPort::AudioPort(const String8& name, audio_port_type_t type,
           audio_port_role_t role, const sp<HwModule>& module) :
-    mName(name), mType(type), mRole(role), mModule(module), mFlags(0)
+    mName(name), mType(type), mRole(role), mModule(module), mFlags(0), mId(0)
 {
     mUseInChannelMask = ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
                     ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
 }
 
+void AudioPolicyManager::AudioPort::attach(const sp<HwModule>& module) {
+    mId = AudioPolicyManager::nextUniqueId();
+    mModule = module;
+}
+
 void AudioPolicyManager::AudioPort::toAudioPort(struct audio_port *port) const
 {
     port->role = mRole;
     port->type = mType;
+    strlcpy(port->name, mName, AUDIO_PORT_MAX_NAME_LEN);
     unsigned int i;
     for (i = 0; i < mSamplingRates.size() && i < AUDIO_PORT_MAX_SAMPLING_RATES; i++) {
         if (mSamplingRates[i] != 0) {
@@ -7441,17 +7483,15 @@
 
 // --- DeviceDescriptor implementation
 
+String8 AudioPolicyManager::DeviceDescriptor::emptyNameStr = String8("");
 
 AudioPolicyManager::DeviceDescriptor::DeviceDescriptor(const String8& name, audio_devices_t type) :
                      AudioPort(name, AUDIO_PORT_TYPE_DEVICE,
                                audio_is_output_device(type) ? AUDIO_PORT_ROLE_SINK :
                                                               AUDIO_PORT_ROLE_SOURCE,
                              NULL),
-                     mDeviceType(type), mAddress(""), mId(0)
+                     mDeviceType(type), mAddress("")
 {
-    if (mGains.size() > 0) {
-        mGains[0]->getDefaultConfig(&mGain);
-    }
 }
 
 bool AudioPolicyManager::DeviceDescriptor::equals(const sp<DeviceDescriptor>& other) const
@@ -7466,6 +7506,15 @@
                 mChannelMask == other->mChannelMask);
 }
 
+void AudioPolicyManager::DeviceDescriptor::loadGains(cnode *root)
+{
+    AudioPort::loadGains(root);
+    if (mGains.size() > 0) {
+        mGains[0]->getDefaultConfig(&mGain);
+    }
+}
+
+
 void AudioPolicyManager::DeviceVector::refreshTypes()
 {
     mDeviceTypes = AUDIO_DEVICE_NONE;
@@ -7528,7 +7577,7 @@
         uint32_t i = 31 - __builtin_clz(types);
         uint32_t type = 1 << i;
         types &= ~type;
-        add(new DeviceDescriptor(String8(""), type | role_bit));
+        add(new DeviceDescriptor(String8("device_type"), type | role_bit));
     }
 }
 
@@ -7542,7 +7591,7 @@
                                  ARRAY_SIZE(sDeviceNameToEnumTable),
                                  devName);
             if (type != AUDIO_DEVICE_NONE) {
-                sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(""), type);
+                sp<DeviceDescriptor> dev = new DeviceDescriptor(String8(name), type);
                 if (type == AUDIO_DEVICE_IN_REMOTE_SUBMIX ||
                         type == AUDIO_DEVICE_OUT_REMOTE_SUBMIX ) {
                     dev->mAddress = String8("0");
@@ -7584,8 +7633,7 @@
 {
     sp<DeviceDescriptor> device;
     for (size_t i = 0; i < size(); i++) {
-        ALOGV("DeviceVector::getDeviceFromId(%d) itemAt(%zu)->mId %d", id, i, itemAt(i)->mId);
-        if (itemAt(i)->mId == id) {
+        if (itemAt(i)->getHandle() == id) {
             device = itemAt(i);
             break;
         }
@@ -7645,13 +7693,17 @@
     }
 
     AudioPortConfig::toAudioPortConfig(dstConfig, srcConfig);
-
     dstConfig->id = mId;
     dstConfig->role = audio_is_output_device(mDeviceType) ?
                         AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
     dstConfig->type = AUDIO_PORT_TYPE_DEVICE;
     dstConfig->ext.device.type = mDeviceType;
-    dstConfig->ext.device.hw_module = mModule->mHandle;
+
+    //TODO Understand why this test is necessary. i.e. why at boot time does it crash
+    // without the test?
+    // This has been demonstrated to NOT be true (at start up)
+    // ALOG_ASSERT(mModule != NULL);
+    dstConfig->ext.device.hw_module = mModule != NULL ? mModule->mHandle : NULL;
     strncpy(dstConfig->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN);
 }
 
@@ -7890,7 +7942,7 @@
                                               ARRAY_SIZE(sDeviceNameToEnumTable),
                                               (char *)node->value);
             if (device != AUDIO_DEVICE_NONE) {
-                mDefaultOutputDevice = new DeviceDescriptor(String8(""), device);
+                mDefaultOutputDevice = new DeviceDescriptor(String8("default-output"), device);
             } else {
                 ALOGW("loadGlobalConfig() default device not specified");
             }
@@ -7941,8 +7993,8 @@
 {
     sp<HwModule> module;
     sp<IOProfile> profile;
-    sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(String8(""),
-                                                                   AUDIO_DEVICE_IN_BUILTIN_MIC);
+    sp<DeviceDescriptor> defaultInputDevice =
+                    new DeviceDescriptor(String8("builtin-mic"), AUDIO_DEVICE_IN_BUILTIN_MIC);
     mAvailableOutputDevices.add(mDefaultOutputDevice);
     mAvailableInputDevices.add(defaultInputDevice);
 
@@ -7975,6 +8027,9 @@
     if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
         return AUDIO_STREAM_BLUETOOTH_SCO;
     }
+    if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
+        return AUDIO_STREAM_TTS;
+    }
 
     // usage to stream type mapping
     switch (attr->usage) {
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index 0fa182b..3e3c662 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -73,7 +73,8 @@
         // AudioPolicyInterface
         virtual status_t setDeviceConnectionState(audio_devices_t device,
                                                           audio_policy_dev_state_t state,
-                                                          const char *device_address);
+                                                          const char *device_address,
+                                                          const char *device_name);
         virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                               const char *device_address);
         virtual void setPhoneState(audio_mode_t state);
@@ -252,6 +253,11 @@
                       audio_port_role_t role, const sp<HwModule>& module);
             virtual ~AudioPort() {}
 
+            audio_port_handle_t getHandle() { return mId; }
+
+            void attach(const sp<HwModule>& module);
+            bool isAttached() { return mId != 0; }
+
             virtual void toAudioPort(struct audio_port *port) const;
 
             void importAudioPort(const sp<AudioPort> port);
@@ -264,7 +270,7 @@
 
             audio_gain_mode_t loadGainMode(char *name);
             void loadGain(cnode *root, int index);
-            void loadGains(cnode *root);
+            virtual void loadGains(cnode *root);
 
             // searches for an exact match
             status_t checkExactSamplingRate(uint32_t samplingRate) const;
@@ -301,6 +307,12 @@
             sp<HwModule> mModule;                 // audio HW module exposing this I/O stream
             uint32_t mFlags; // attribute flags (e.g primary output,
                                                 // direct output...).
+
+        protected:
+            //TODO - clarify the role of mId in this case, both an "attached" indicator
+            // and a unique ID for identifying a port to the (upcoming) selection API,
+            // and its relationship to the mId in AudioOutputDescriptor and AudioInputDescriptor.
+            audio_port_handle_t mId;
         };
 
         class AudioPortConfig: public virtual RefBase
@@ -344,17 +356,22 @@
             virtual ~DeviceDescriptor() {}
 
             bool equals(const sp<DeviceDescriptor>& other) const;
+
+            // AudioPortConfig
+            virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
             virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
                                    const struct audio_port_config *srcConfig = NULL) const;
-            virtual sp<AudioPort> getAudioPort() const { return (AudioPort*) this; }
 
+            // AudioPort
+            virtual void loadGains(cnode *root);
             virtual void toAudioPort(struct audio_port *port) const;
 
             status_t dump(int fd, int spaces, int index) const;
 
             audio_devices_t mDeviceType;
             String8 mAddress;
-            audio_port_handle_t mId;
+
+            static String8  emptyNameStr;
         };
 
         class DeviceVector : public SortedVector< sp<DeviceDescriptor> >
@@ -828,7 +845,7 @@
                                 // to boost soft sounds, used to adjust volume curves accordingly
 
         Vector < sp<HwModule> > mHwModules;
-        volatile int32_t mNextUniqueId;
+        static volatile int32_t mNextUniqueId;
         volatile int32_t mAudioPortGeneration;
 
         DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
@@ -878,7 +895,7 @@
         static float volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
                 int indexInUi);
         static bool isVirtualInputDevice(audio_devices_t device);
-        uint32_t nextUniqueId();
+        static uint32_t nextUniqueId();
         uint32_t nextAudioPortGeneration();
 private:
         // updates device caching and output for streams that can influence the
@@ -924,7 +941,10 @@
         // Called by setDeviceConnectionState().
         status_t setDeviceConnectionStateInt(audio_devices_t device,
                                                           audio_policy_dev_state_t state,
-                                                          const char *device_address);
+                                                          const char *device_address,
+                                                          const char *device_name);
+        sp<DeviceDescriptor>  getDeviceDescriptor(const audio_devices_t device,
+                                                  const char *device_address);
 };
 
 };
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index b80380e..eb9116d 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -908,8 +908,10 @@
     }
     removedCommands.clear();
 
-    // Disable wait for status if delay is not 0
-    if (delayMs != 0) {
+    // Disable wait for status if delay is not 0.
+    // Except for create audio patch command because the returned patch handle
+    // is needed by audio policy manager
+    if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) {
         command->mWaitStatus = false;
     }
 
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 80284a4..7c2b59d 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -61,7 +61,8 @@
 
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
-                                              const char *device_address);
+                                              const char *device_address,
+                                              const char *device_name);
     virtual audio_policy_dev_state_t getDeviceConnectionState(
                                                                 audio_devices_t device,
                                                                 const char *device_address);
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index e184d97..de9551d 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -25,6 +25,7 @@
     CameraDeviceFactory.cpp \
     common/Camera2ClientBase.cpp \
     common/CameraDeviceBase.cpp \
+    common/CameraModule.cpp \
     common/FrameProcessorBase.cpp \
     api1/CameraClient.cpp \
     api1/Camera2Client.cpp \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 1232c32..485b979 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -113,14 +113,17 @@
 
     BnCameraService::onFirstRef();
 
+    camera_module_t *rawModule;
     if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
-                (const hw_module_t **)&mModule) < 0) {
+                (const hw_module_t **)&rawModule) < 0) {
         ALOGE("Could not load camera HAL module");
         mNumberOfCameras = 0;
     }
     else {
-        ALOGI("Loaded \"%s\" camera module", mModule->common.name);
-        mNumberOfCameras = mModule->get_number_of_cameras();
+        mModule = new CameraModule(rawModule);
+        const hw_module_t *common = mModule->getRawModule();
+        ALOGI("Loaded \"%s\" camera module", common->name);
+        mNumberOfCameras = mModule->getNumberOfCameras();
         if (mNumberOfCameras > MAX_CAMERAS) {
             ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
                     mNumberOfCameras, MAX_CAMERAS);
@@ -130,14 +133,13 @@
             setCameraFree(i);
         }
 
-        if (mModule->common.module_api_version >=
-                CAMERA_MODULE_API_VERSION_2_1) {
-            mModule->set_callbacks(this);
+        if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_1) {
+            mModule->setCallbacks(this);
         }
 
         VendorTagDescriptor::clearGlobalVendorTagDescriptor();
 
-        if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
+        if (common->module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
             setUpVendorTags();
         }
 
@@ -152,6 +154,9 @@
         }
     }
 
+    if (mModule) {
+        delete mModule;
+    }
     VendorTagDescriptor::clearGlobalVendorTagDescriptor();
     gCameraService = NULL;
 }
@@ -236,7 +241,7 @@
 
     struct camera_info info;
     status_t rc = filterGetInfoErrorCode(
-        mModule->get_camera_info(cameraId, &info));
+        mModule->getCameraInfo(cameraId, &info));
     cameraInfo->facing = info.facing;
     cameraInfo->orientation = info.orientation;
     return rc;
@@ -347,7 +352,7 @@
 
     int facing;
     status_t ret = OK;
-    if (mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
+    if (mModule->getRawModule()->module_api_version < CAMERA_MODULE_API_VERSION_2_0 ||
             getDeviceVersion(cameraId, &facing) <= CAMERA_DEVICE_API_VERSION_2_1 ) {
         /**
          * Backwards compatibility mode for old HALs:
@@ -368,7 +373,7 @@
          * Normal HAL 2.1+ codepath.
          */
         struct camera_info info;
-        ret = filterGetInfoErrorCode(mModule->get_camera_info(cameraId, &info));
+        ret = filterGetInfoErrorCode(mModule->getCameraInfo(cameraId, &info));
         *cameraInfo = info.static_camera_characteristics;
     }
 
@@ -387,12 +392,12 @@
 
 int CameraService::getDeviceVersion(int cameraId, int* facing) {
     struct camera_info info;
-    if (mModule->get_camera_info(cameraId, &info) != OK) {
+    if (mModule->getCameraInfo(cameraId, &info) != OK) {
         return -1;
     }
 
     int deviceVersion;
-    if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
+    if (mModule->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_0) {
         deviceVersion = info.device_version;
     } else {
         deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
@@ -433,13 +438,13 @@
     vendor_tag_ops_t vOps = vendor_tag_ops_t();
 
     // Check if vendor operations have been implemented
-    if (mModule->get_vendor_tag_ops == NULL) {
+    if (!mModule->isVendorTagDefined()) {
         ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__);
         return false;
     }
 
     ATRACE_BEGIN("camera3->get_metadata_vendor_tag_ops");
-    mModule->get_vendor_tag_ops(&vOps);
+    mModule->getVendorTagOps(&vOps);
     ATRACE_END();
 
     // Ensure all vendor operations are present
@@ -789,8 +794,9 @@
         /*out*/
         sp<ICamera>& device) {
 
+    int apiVersion = mModule->getRawModule()->module_api_version;
     if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
-            mModule->common.module_api_version < CAMERA_MODULE_API_VERSION_2_3) {
+            apiVersion < CAMERA_MODULE_API_VERSION_2_3) {
         /*
          * Either the HAL version is unspecified in which case this just creates
          * a camera client selected by the latest device version, or
@@ -798,7 +804,7 @@
          * the open_legacy call
          */
         ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
-                __FUNCTION__, mModule->common.module_api_version);
+                __FUNCTION__, apiVersion);
         return INVALID_OPERATION;
     }
 
@@ -1633,14 +1639,11 @@
             return NO_ERROR;
         }
 
-        result = String8::format("Camera module HAL API version: 0x%x\n",
-                mModule->common.hal_api_version);
-        result.appendFormat("Camera module API version: 0x%x\n",
-                mModule->common.module_api_version);
-        result.appendFormat("Camera module name: %s\n",
-                mModule->common.name);
-        result.appendFormat("Camera module author: %s\n",
-                mModule->common.author);
+        const hw_module_t* common = mModule->getRawModule();
+        result = String8::format("Camera module HAL API version: 0x%x\n", common->hal_api_version);
+        result.appendFormat("Camera module API version: 0x%x\n", common->module_api_version);
+        result.appendFormat("Camera module name: %s\n", common->name);
+        result.appendFormat("Camera module author: %s\n", common->author);
         result.appendFormat("Number of camera devices: %d\n\n", mNumberOfCameras);
 
         sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
@@ -1660,7 +1663,7 @@
             result = String8::format("Camera %d static information:\n", i);
             camera_info info;
 
-            status_t rc = mModule->get_camera_info(i, &info);
+            status_t rc = mModule->getCameraInfo(i, &info);
             if (rc != OK) {
                 result.appendFormat("  Error reading static information!\n");
                 write(fd, result.string(), result.size());
@@ -1669,8 +1672,7 @@
                         info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
                 result.appendFormat("  Orientation: %d\n", info.orientation);
                 int deviceVersion;
-                if (mModule->common.module_api_version <
-                        CAMERA_MODULE_API_VERSION_2_0) {
+                if (common->module_api_version < CAMERA_MODULE_API_VERSION_2_0) {
                     deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
                 } else {
                     deviceVersion = info.device_version;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 126d8d9..7d0df3a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -37,6 +37,8 @@
 
 #include <camera/ICameraServiceListener.h>
 
+#include "common/CameraModule.h"
+
 /* This needs to be increased if we can have more cameras */
 #define MAX_CAMERAS 2
 
@@ -153,7 +155,7 @@
 
     class BasicClient : public virtual RefBase {
     public:
-        virtual status_t    initialize(camera_module_t *module) = 0;
+        virtual status_t    initialize(CameraModule *module) = 0;
         virtual void        disconnect();
 
         // because we can't virtually inherit IInterface, which breaks
@@ -385,7 +387,7 @@
     sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
     int                 mSoundRef;  // reference count (release all MediaPlayer when 0)
 
-    camera_module_t *mModule;
+    CameraModule*     mModule;
 
     Vector<sp<ICameraServiceListener> >
                         mListenerList;
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 0ed5586..4ac5166 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -67,7 +67,7 @@
     mLegacyMode = legacyMode;
 }
 
-status_t Camera2Client::initialize(camera_module_t *module)
+status_t Camera2Client::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index d68bb29..5a8241f 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -94,7 +94,7 @@
 
     virtual ~Camera2Client();
 
-    status_t initialize(camera_module_t *module);
+    status_t initialize(CameraModule *module);
 
     virtual status_t dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index bbb2fe0..6bea3b6 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -59,7 +59,7 @@
     LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
 }
 
-status_t CameraClient::initialize(camera_module_t *module) {
+status_t CameraClient::initialize(CameraModule *module) {
     int callingPid = getCallingPid();
     status_t res;
 
@@ -75,7 +75,7 @@
     snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
 
     mHardware = new CameraHardwareInterface(camera_device_name);
-    res = mHardware->initialize(&module->common);
+    res = mHardware->initialize(module);
     if (res != OK) {
         ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                 __FUNCTION__, mCameraId, strerror(-res), res);
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 63a9d0f..95616b2 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -68,7 +68,7 @@
             bool legacyMode = false);
     ~CameraClient();
 
-    status_t initialize(camera_module_t *module);
+    status_t initialize(CameraModule *module);
 
     status_t dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 6a1ee44..acc092c 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -71,7 +71,7 @@
     ALOGI("CameraDeviceClient %d: Opened", cameraId);
 }
 
-status_t CameraDeviceClient::initialize(camera_module_t *module)
+status_t CameraDeviceClient::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     status_t res;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 84e46b7..e687175 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -119,7 +119,7 @@
             int servicePid);
     virtual ~CameraDeviceClient();
 
-    virtual status_t      initialize(camera_module_t *module);
+    virtual status_t      initialize(CameraModule *module);
 
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
index 59e5083..30a89c2 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.cpp
@@ -50,7 +50,7 @@
     mExclusiveLock = false;
 }
 
-status_t ProCamera2Client::initialize(camera_module_t *module)
+status_t ProCamera2Client::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     status_t res;
diff --git a/services/camera/libcameraservice/api_pro/ProCamera2Client.h b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
index 9d83122..7f5f6ac 100644
--- a/services/camera/libcameraservice/api_pro/ProCamera2Client.h
+++ b/services/camera/libcameraservice/api_pro/ProCamera2Client.h
@@ -85,7 +85,7 @@
             int servicePid);
     virtual ~ProCamera2Client();
 
-    virtual status_t      initialize(camera_module_t *module);
+    virtual status_t      initialize(CameraModule *module);
 
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 453c8bd..0415d67 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -78,7 +78,7 @@
 }
 
 template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
+status_t Camera2ClientBase<TClientBase>::initialize(CameraModule *module) {
     ATRACE_CALL();
     ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
           TClientBase::mCameraId);
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index e09c1b5..eb21d55 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -18,6 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H
 
 #include "common/CameraDeviceBase.h"
+#include "common/CameraModule.h"
 #include "camera/CaptureResult.h"
 
 namespace android {
@@ -55,7 +56,7 @@
                       int servicePid);
     virtual ~Camera2ClientBase();
 
-    virtual status_t      initialize(camera_module_t *module);
+    virtual status_t      initialize(CameraModule *module);
     virtual status_t      dump(int fd, const Vector<String16>& args);
 
     /**
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index d26e20c..06615f6 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -29,6 +29,7 @@
 #include "hardware/camera3.h"
 #include "camera/CameraMetadata.h"
 #include "camera/CaptureResult.h"
+#include "common/CameraModule.h"
 
 namespace android {
 
@@ -45,7 +46,7 @@
      */
     virtual int      getId() const = 0;
 
-    virtual status_t initialize(camera_module_t *module) = 0;
+    virtual status_t initialize(CameraModule *module) = 0;
     virtual status_t disconnect() = 0;
 
     virtual status_t dump(int fd, const Vector<String16> &args) = 0;
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
new file mode 100644
index 0000000..bbf47e8
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "CameraModule"
+//#define LOG_NDEBUG 0
+
+#include "CameraModule.h"
+
+namespace android {
+
+void CameraModule::deriveCameraCharacteristicsKeys(
+        uint32_t deviceVersion, CameraMetadata &chars) {
+    // HAL1 devices should not reach here
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_2_0) {
+        ALOGV("%s: Cannot derive keys for HAL version < 2.0");
+        return;
+    }
+
+    // Keys added in HAL3.3
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+        Vector<uint8_t> controlModes;
+        uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
+        chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
+        data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
+        chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
+        controlModes.push(ANDROID_CONTROL_MODE_OFF);
+        controlModes.push(ANDROID_CONTROL_MODE_AUTO);
+        camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+        if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
+            controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
+        }
+        chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+    }
+    return;
+}
+
+CameraModule::CameraModule(camera_module_t *module) {
+    if (module == NULL) {
+        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
+        assert(0);
+    }
+
+    mModule = module;
+    for (int i = 0; i < MAX_CAMERAS_PER_MODULE; i++) {
+        mCameraInfoCached[i] = false;
+    }
+}
+
+int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
+    Mutex::Autolock lock(mCameraInfoLock);
+    if (cameraId < 0 || cameraId >= MAX_CAMERAS_PER_MODULE) {
+        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+        return -EINVAL;
+    }
+
+    camera_info &wrappedInfo = mCameraInfo[cameraId];
+    if (!mCameraInfoCached[cameraId]) {
+        camera_info rawInfo;
+        int ret = mModule->get_camera_info(cameraId, &rawInfo);
+        if (ret != 0) {
+            return ret;
+        }
+        CameraMetadata &m = mCameraCharacteristics[cameraId];
+        m = rawInfo.static_camera_characteristics;
+        int deviceVersion;
+        int apiVersion = mModule->common.module_api_version;
+        if (apiVersion >= CAMERA_MODULE_API_VERSION_2_0) {
+            deviceVersion = rawInfo.device_version;
+        } else {
+            deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
+        }
+        deriveCameraCharacteristicsKeys(deviceVersion, m);
+        wrappedInfo = rawInfo;
+        wrappedInfo.static_camera_characteristics = m.getAndLock();
+        mCameraInfoCached[cameraId] = true;
+    }
+    *info = wrappedInfo;
+    return 0;
+}
+
+int CameraModule::open(const char* id, struct hw_device_t** device) {
+    return mModule->common.methods->open(&mModule->common, id, device);
+}
+
+int CameraModule::openLegacy(
+        const char* id, uint32_t halVersion, struct hw_device_t** device) {
+    return mModule->open_legacy(&mModule->common, id, halVersion, device);
+}
+
+const hw_module_t* CameraModule::getRawModule() {
+    return &mModule->common;
+}
+
+int CameraModule::getNumberOfCameras() {
+    return mModule->get_number_of_cameras();
+}
+
+int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
+    return mModule->set_callbacks(callbacks);
+}
+
+bool CameraModule::isVendorTagDefined() {
+    return mModule->get_vendor_tag_ops != NULL;
+}
+
+void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
+    if (mModule->get_vendor_tag_ops) {
+        mModule->get_vendor_tag_ops(ops);
+    }
+}
+
+int CameraModule::setTorchMode(const char* camera_id, bool enable) {
+    return mModule->set_torch_mode(camera_id, enable);
+}
+
+}; // namespace android
+
diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h
new file mode 100644
index 0000000..31b9ae2
--- /dev/null
+++ b/services/camera/libcameraservice/common/CameraModule.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+#define ANDROID_SERVERS_CAMERA_CAMERAMODULE_H
+
+#include <hardware/camera.h>
+#include <camera/CameraMetadata.h>
+#include <utils/Mutex.h>
+
+/* This needs to be increased if we can have more cameras */
+#define MAX_CAMERAS_PER_MODULE 2
+
+
+namespace android {
+/**
+ * A wrapper class for HAL camera module.
+ *
+ * This class wraps camera_module_t returned from HAL to provide a wrapped
+ * get_camera_info implementation which CameraService generates some
+ * camera characteristics keys defined in newer HAL version on an older HAL.
+ */
+class CameraModule {
+public:
+    CameraModule(camera_module_t *module);
+
+    const hw_module_t* getRawModule();
+    int getCameraInfo(int cameraId, struct camera_info *info);
+    int getNumberOfCameras(void);
+    int open(const char* id, struct hw_device_t** device);
+    int openLegacy(const char* id, uint32_t halVersion, struct hw_device_t** device);
+    int setCallbacks(const camera_module_callbacks_t *callbacks);
+    bool isVendorTagDefined();
+    void getVendorTagOps(vendor_tag_ops_t* ops);
+    int setTorchMode(const char* camera_id, bool enable);
+
+private:
+    // Derive camera characteristics keys defined after HAL device version
+    static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars);
+    camera_module_t *mModule;
+    CameraMetadata mCameraCharacteristics[MAX_CAMERAS_PER_MODULE];
+    camera_info mCameraInfo[MAX_CAMERAS_PER_MODULE];
+    bool mCameraInfoCached[MAX_CAMERAS_PER_MODULE];
+    Mutex mCameraInfoLock;
+};
+
+} // namespace android
+
+#endif
+
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index 1935c2b..9e1cdc9 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -89,24 +89,23 @@
         }
     }
 
-    status_t initialize(hw_module_t *module)
+    status_t initialize(CameraModule *module)
     {
         ALOGI("Opening camera %s", mName.string());
-        camera_module_t *cameraModule = reinterpret_cast<camera_module_t *>(module);
         camera_info info;
-        status_t res = cameraModule->get_camera_info(atoi(mName.string()), &info);
+        status_t res = module->getCameraInfo(atoi(mName.string()), &info);
         if (res != OK) return res;
 
         int rc = OK;
-        if (module->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
+        if (module->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_3 &&
             info.device_version > CAMERA_DEVICE_API_VERSION_1_0) {
             // Open higher version camera device as HAL1.0 device.
-            rc = cameraModule->open_legacy(module, mName.string(),
-                                               CAMERA_DEVICE_API_VERSION_1_0,
-                                               (hw_device_t **)&mDevice);
+            rc = module->openLegacy(mName.string(),
+                                     CAMERA_DEVICE_API_VERSION_1_0,
+                                     (hw_device_t **)&mDevice);
         } else {
-            rc = CameraService::filterOpenErrorCode(module->methods->open(
-                module, mName.string(), (hw_device_t **)&mDevice));
+            rc = CameraService::filterOpenErrorCode(module->open(
+                    mName.string(), (hw_device_t **)&mDevice));
         }
         if (rc != OK) {
             ALOGE("Could not open camera %s: %d", mName.string(), rc);
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index d1158d6..be66c4d 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -53,7 +53,7 @@
     return mId;
 }
 
-status_t Camera2Device::initialize(camera_module_t *module)
+status_t Camera2Device::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
@@ -68,8 +68,8 @@
 
     camera2_device_t *device;
 
-    res = CameraService::filterOpenErrorCode(module->common.methods->open(
-        &module->common, name, reinterpret_cast<hw_device_t**>(&device)));
+    res = CameraService::filterOpenErrorCode(module->open(
+            name, reinterpret_cast<hw_device_t**>(&device)));
 
     if (res != OK) {
         ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
@@ -87,7 +87,7 @@
     }
 
     camera_info info;
-    res = module->get_camera_info(mId, &info);
+    res = module->getCameraInfo(mId, &info);
     if (res != OK ) return res;
 
     if (info.device_version != device->common.version) {
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 4def8ae..1cc5482 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -43,7 +43,7 @@
      * CameraDevice interface
      */
     virtual int      getId() const;
-    virtual status_t initialize(camera_module_t *module);
+    virtual status_t initialize(CameraModule *module);
     virtual status_t disconnect();
     virtual status_t dump(int fd, const Vector<String16>& args);
     virtual const CameraMetadata& info() const;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index bba3905..9a4e5ac 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -86,7 +86,7 @@
  * CameraDeviceBase interface
  */
 
-status_t Camera3Device::initialize(camera_module_t *module)
+status_t Camera3Device::initialize(CameraModule *module)
 {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
@@ -106,9 +106,8 @@
     camera3_device_t *device;
 
     ATRACE_BEGIN("camera3->open");
-    res = CameraService::filterOpenErrorCode(module->common.methods->open(
-        &module->common, deviceName.string(),
-        reinterpret_cast<hw_device_t**>(&device)));
+    res = CameraService::filterOpenErrorCode(module->open(
+            deviceName.string(), reinterpret_cast<hw_device_t**>(&device)));
     ATRACE_END();
 
     if (res != OK) {
@@ -127,7 +126,7 @@
     }
 
     camera_info info;
-    res = CameraService::filterGetInfoErrorCode(module->get_camera_info(
+    res = CameraService::filterGetInfoErrorCode(module->getCameraInfo(
         mId, &info));
     if (res != OK) return res;
 
@@ -361,16 +360,15 @@
         return BAD_VALUE;
     }
     maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
+    assert(kMinJpegBufferSize < maxJpegBufferSize);
 
     // Calculate final jpeg buffer size for the given resolution.
     float scaleFactor = ((float) (width * height)) /
             (maxJpegResolution.width * maxJpegResolution.height);
-    ssize_t jpegBufferSize = scaleFactor * maxJpegBufferSize;
-    // Bound the buffer size to [MIN_JPEG_BUFFER_SIZE, maxJpegBufferSize].
+    ssize_t jpegBufferSize = scaleFactor * (maxJpegBufferSize - kMinJpegBufferSize) +
+            kMinJpegBufferSize;
     if (jpegBufferSize > maxJpegBufferSize) {
         jpegBufferSize = maxJpegBufferSize;
-    } else if (jpegBufferSize < kMinJpegBufferSize) {
-        jpegBufferSize = kMinJpegBufferSize;
     }
 
     return jpegBufferSize;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index ec8dc10..de10cfe 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -73,7 +73,7 @@
     virtual int      getId() const;
 
     // Transitions to idle state on success.
-    virtual status_t initialize(camera_module_t *module);
+    virtual status_t initialize(CameraModule *module);
     virtual status_t disconnect();
     virtual status_t dump(int fd, const Vector<String16> &args);
     virtual const CameraMetadata& info() const;