Merge "tunnel NuPlayer source and decoder input" into lmp-mr1-dev
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index e09567a..d050c78 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -310,6 +310,13 @@
 }
 
 status_t NuPlayerDriver::pause() {
+    // The NuPlayerRenderer may get flushed if pause for long enough, e.g. the pause timeout tear
+    // down for audio offload mode. If that happens, the NuPlayerRenderer will no longer know the
+    // current position. So similar to seekTo, update |mPositionUs| to the pause position by calling
+    // getCurrentPosition here.
+    int msec;
+    getCurrentPosition(&msec);
+
     Mutex::Autolock autoLock(mLock);
 
     switch (mState) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 920554b..f7d30a8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1047,6 +1047,7 @@
          Mutex::Autolock autoLock(mLock);
          syncQueuesDone_l();
          setPauseStartedTimeRealUs(-1);
+         setAnchorTime(-1, -1);
     }
 
     ALOGV("flushing %s", audio ? "audio" : "video");
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 71a6a73..0f11b34 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4694,15 +4694,15 @@
 
 ssize_t AudioFlinger::DuplicatingThread::threadLoop_write()
 {
+    // We convert the duplicating thread format to AUDIO_FORMAT_PCM_16_BIT
+    // for delivery downstream as needed. This in-place conversion is safe as
+    // AUDIO_FORMAT_PCM_16_BIT is smaller than any other supported format
+    // (AUDIO_FORMAT_PCM_8_BIT is not allowed here).
+    if (mFormat != AUDIO_FORMAT_PCM_16_BIT) {
+        memcpy_by_audio_format(mSinkBuffer, AUDIO_FORMAT_PCM_16_BIT,
+                               mSinkBuffer, mFormat, writeFrames * mChannelCount);
+    }
     for (size_t i = 0; i < outputTracks.size(); i++) {
-        // We convert the duplicating thread format to AUDIO_FORMAT_PCM_16_BIT
-        // for delivery downstream as needed. This in-place conversion is safe as
-        // AUDIO_FORMAT_PCM_16_BIT is smaller than any other supported format
-        // (AUDIO_FORMAT_PCM_8_BIT is not allowed here).
-        if (mFormat != AUDIO_FORMAT_PCM_16_BIT) {
-            memcpy_by_audio_format(mSinkBuffer, AUDIO_FORMAT_PCM_16_BIT,
-                    mSinkBuffer, mFormat, writeFrames * mChannelCount);
-        }
         outputTracks[i]->write(reinterpret_cast<int16_t*>(mSinkBuffer), writeFrames);
     }
     mStandby = false;
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index b5aaee3..d3b67f6 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -535,6 +535,16 @@
             (struct sound_trigger_sound_model *)modelMemory->pointer();
 
     AutoMutex lock(mLock);
+
+    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
+        if (mModels.size() == 0) {
+            return INVALID_OPERATION;
+        }
+        ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one",
+              mDescriptor.properties.max_sound_models);
+        unloadSoundModel_l(mModels.valueAt(0)->mHandle);
+    }
+
     status_t status = mHwDevice->load_sound_model(mHwDevice,
                                                   sound_model,
                                                   SoundTriggerHwService::soundModelCallback,
@@ -566,6 +576,11 @@
     }
 
     AutoMutex lock(mLock);
+    return unloadSoundModel_l(handle);
+}
+
+status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
+{
     ssize_t index = mModels.indexOfKey(handle);
     if (index < 0) {
         return BAD_VALUE;
@@ -574,6 +589,7 @@
     mModels.removeItem(handle);
     if (model->mState == Model::STATE_ACTIVE) {
         mHwDevice->stop_recognition(mHwDevice, model->mHandle);
+        model->mState = Model::STATE_IDLE;
     }
     AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
     return mHwDevice->unload_sound_model(mHwDevice, handle);
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index d05dacd..2619a5f 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -141,6 +141,9 @@
 
     private:
 
+       status_t unloadSoundModel_l(sound_model_handle_t handle);
+
+
         Mutex                                  mLock;
         wp<SoundTriggerHwService>              mService;
         struct sound_trigger_hw_device*        mHwDevice;