Merge "NuPlayerRenderer: prepareForMediaRenderingStart_l on en/disable offload audio" into mnc-dev
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 3868f13..011b31f 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -1235,11 +1235,15 @@
 void AudioRecord::AudioRecordThread::wake()
 {
     AutoMutex _l(mMyLock);
-    if (!mPaused && mPausedInt && mPausedNs > 0) {
-        // audio record is active and internally paused with timeout.
+    if (!mPaused) {
+        // wake() might be called while servicing a callback - ignore the next
+        // pause time and call processAudioBuffer.
         mIgnoreNextPausedInt = true;
-        mPausedInt = false;
-        mMyCond.signal();
+        if (mPausedInt && mPausedNs > 0) {
+            // audio record is active and internally paused with timeout.
+            mPausedInt = false;
+            mMyCond.signal();
+        }
     }
 }
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ab720c6..7befe5d 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -483,7 +483,6 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
-    mServer = 0;
     mPosition = 0;
     mReleased = 0;
     mStartUs = 0;
@@ -1389,6 +1388,9 @@
         mReqFrameCount = frameCount;
     }
 
+    // reset server position to 0 as we have new cblk.
+    mServer = 0;
+
     // update proxy
     if (mSharedBuffer == 0) {
         mStaticProxy.clear();
@@ -2109,15 +2111,13 @@
     // If a new IAudioTrack cannot be created, the previous (dead) instance will be left intact.
     status_t result = createTrack_l();
 
-    // take the frames that will be lost by track recreation into account in saved position
-    // For streaming tracks, this is the amount we obtained from the user/client
-    // (not the number actually consumed at the server - those are already lost).
-    (void) updateAndGetPosition_l();
-    if (mStaticProxy == 0) {
-        mPosition = mReleased;
-    }
-
     if (result == NO_ERROR) {
+        // take the frames that will be lost by track recreation into account in saved position
+        // For streaming tracks, this is the amount we obtained from the user/client
+        // (not the number actually consumed at the server - those are already lost).
+        if (mStaticProxy == 0) {
+            mPosition = mReleased;
+        }
         // Continue playback from last known position and restore loop.
         if (mStaticProxy != 0) {
             if (loopCount != 0) {
@@ -2551,11 +2551,15 @@
 void AudioTrack::AudioTrackThread::wake()
 {
     AutoMutex _l(mMyLock);
-    if (!mPaused && mPausedInt && mPausedNs > 0) {
-        // audio track is active and internally paused with timeout.
+    if (!mPaused) {
+        // wake() might be called while servicing a callback - ignore the next
+        // pause time and call processAudioBuffer.
         mIgnoreNextPausedInt = true;
-        mPausedInt = false;
-        mMyCond.signal();
+        if (mPausedInt && mPausedNs > 0) {
+            // audio track is active and internally paused with timeout.
+            mPausedInt = false;
+            mMyCond.signal();
+        }
     }
 }
 
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index c215abf..502ab2d 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -574,6 +574,7 @@
             ALOGE("reset() failed with return code (%d)", ret);
             mCurrentState = MEDIA_PLAYER_STATE_ERROR;
         } else {
+            mPlayer->disconnect();
             mCurrentState = MEDIA_PLAYER_IDLE;
         }
         // setDataSource has to be called again to create a
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index d49ba93..56521a2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -655,6 +655,7 @@
     }
 
     if (!p->hardwareOutput()) {
+        Mutex::Autolock l(mLock);
         mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
                 mPid, mAudioAttributes);
         static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
@@ -1101,6 +1102,9 @@
 {
     if (mAudioAttributes != NULL) { free(mAudioAttributes); }
     mAudioAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+    if (mAudioAttributes == NULL) {
+        return NO_MEMORY;
+    }
     unmarshallAudioAttributes(parcel, mAudioAttributes);
 
     ALOGV("setAudioAttributes_l() usage=%d content=%d flags=0x%x tags=%s",
@@ -1337,7 +1341,6 @@
       mCallbackData(NULL),
       mBytesWritten(0),
       mStreamType(AUDIO_STREAM_MUSIC),
-      mAttributes(attr),
       mLeftVolume(1.0),
       mRightVolume(1.0),
       mPlaybackRate(AUDIO_PLAYBACK_RATE_DEFAULT),
@@ -1353,7 +1356,13 @@
 {
     ALOGV("AudioOutput(%d)", sessionId);
     if (attr != NULL) {
-        mStreamType = audio_attributes_to_stream_type(attr);
+        mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+        if (mAttributes != NULL) {
+            memcpy(mAttributes, attr, sizeof(audio_attributes_t));
+            mStreamType = audio_attributes_to_stream_type(attr);
+        }
+    } else {
+        mAttributes = NULL;
     }
 
     setMinBufferCount();
@@ -1362,6 +1371,7 @@
 MediaPlayerService::AudioOutput::~AudioOutput()
 {
     close();
+    free(mAttributes);
     delete mCallbackData;
 }
 
@@ -1468,14 +1478,21 @@
 
 void MediaPlayerService::AudioOutput::setAudioAttributes(const audio_attributes_t * attributes) {
     Mutex::Autolock lock(mLock);
-    mAttributes = attributes;
-    if (attributes != NULL) {
+    if (attributes == NULL) {
+        free(mAttributes);
+        mAttributes = NULL;
+    } else {
+        if (mAttributes == NULL) {
+            mAttributes = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
+        }
+        memcpy(mAttributes, attributes, sizeof(audio_attributes_t));
         mStreamType = audio_attributes_to_stream_type(attributes);
     }
 }
 
 void MediaPlayerService::AudioOutput::setAudioStreamType(audio_stream_type_t streamType)
 {
+    Mutex::Autolock lock(mLock);
     // do not allow direct stream type modification if attributes have been set
     if (mAttributes == NULL) {
         mStreamType = streamType;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 1c32597..60d4617 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -142,7 +142,7 @@
         CallbackData *          mCallbackData;
         uint64_t                mBytesWritten;
         audio_stream_type_t     mStreamType;
-        const audio_attributes_t *mAttributes;
+        audio_attributes_t *    mAttributes;
         float                   mLeftVolume;
         float                   mRightVolume;
         AudioPlaybackRate       mPlaybackRate;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8f1e050..9ec5802 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -181,7 +181,6 @@
       mIsLowRamDevice(true),
       mIsDeviceTypeKnown(false),
       mGlobalEffectEnableTime(0),
-      mPrimaryOutputSampleRate(0),
       mSystemReady(false)
 {
     getpid_cached = getpid();
@@ -1869,8 +1868,6 @@
             mHardwareStatus = AUDIO_HW_SET_MODE;
             mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode);
             mHardwareStatus = AUDIO_HW_IDLE;
-
-            mPrimaryOutputSampleRate = config->sample_rate;
         }
         return NO_ERROR;
     }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4f7e27d..20c34ef 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -763,9 +763,7 @@
 
     sp<PatchPanel> mPatchPanel;
 
-    uint32_t    mPrimaryOutputSampleRate;   // sample rate of the primary output, or zero if none
-                                            // protected by mHardwareLock
-    bool       mSystemReady;
+    bool        mSystemReady;
 };
 
 #undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c360051..0a7d4a2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -125,10 +125,15 @@
 static const uint32_t kMaxThreadSleepTimeShift = 2;
 
 // minimum normal sink buffer size, expressed in milliseconds rather than frames
+// FIXME This should be based on experimentally observed scheduling jitter
 static const uint32_t kMinNormalSinkBufferSizeMs = 20;
 // maximum normal sink buffer size
 static const uint32_t kMaxNormalSinkBufferSizeMs = 24;
 
+// minimum capture buffer size in milliseconds to _not_ need a fast capture thread
+// FIXME This should be based on experimentally observed scheduling jitter
+static const uint32_t kMinNormalCaptureBufferSizeMs = 12;
+
 // Offloaded output thread standby delay: allows track transition without going to standby
 static const nsecs_t kOffloadStandbyDelayNs = seconds(1);
 
@@ -5490,20 +5495,7 @@
         initFastCapture = true;
         break;
     case FastCapture_Static:
-        uint32_t primaryOutputSampleRate;
-        {
-            AutoMutex _l(audioFlinger->mHardwareLock);
-            primaryOutputSampleRate = audioFlinger->mPrimaryOutputSampleRate;
-        }
-        initFastCapture =
-                // either capture sample rate is same as (a reasonable) primary output sample rate
-                ((isMusicRate(primaryOutputSampleRate) &&
-                    (mSampleRate == primaryOutputSampleRate)) ||
-                // or primary output sample rate is unknown, and capture sample rate is reasonable
-                ((primaryOutputSampleRate == 0) &&
-                        isMusicRate(mSampleRate))) &&
-                // and the buffer size is < 12 ms
-                (mFrameCount * 1000) / mSampleRate < 12;
+        initFastCapture = (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
         break;
     // case FastCapture_Dynamic:
     }
@@ -6651,7 +6643,7 @@
     if (mResampler != NULL) {
         mBufFrameSize = max(mSrcChannelCount, FCC_2)
                 * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT);
-    } else if ((mIsLegacyUpmix || mIsLegacyDownmix) && mDstFormat != AUDIO_FORMAT_PCM_FLOAT) {
+    } else if (mIsLegacyUpmix || mIsLegacyDownmix) { // legacy modes always float
         mBufFrameSize = mDstChannelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT);
     } else if (mSrcChannelMask != mDstChannelMask && mDstFormat != mSrcFormat) {
         mBufFrameSize = mDstChannelCount * audio_bytes_per_sample(mSrcFormat);