Merge "Fix memory leak in getConnectionState" into lmp-dev
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index cdb7e69..f0f4e45 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -141,13 +141,17 @@
     int32_t totalBitrate = 0;
 
     for (size_t i = 0; i < extractor->countTracks(); ++i) {
+        sp<MediaSource> track = extractor->getTrack(i);
+
         sp<MetaData> meta = extractor->getTrackMetaData(i);
 
         const char *mime;
         CHECK(meta->findCString(kKeyMIMEType, &mime));
 
-        sp<MediaSource> track = extractor->getTrack(i);
-
+        // Do the string compare immediately with "mime",
+        // we can't assume "mime" would stay valid after another
+        // extractor operation, some extractors might modify meta
+        // during getTrack() and make it invalid.
         if (!strncasecmp(mime, "audio/", 6)) {
             if (mAudioTrack.mSource == NULL) {
                 mAudioTrack.mIndex = i;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index f4cd02c..2b7457b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -280,7 +280,7 @@
         msg->setObject(
                 "native-window",
                 new NativeWindowWrapper(
-                    new Surface(bufferProducer)));
+                    new Surface(bufferProducer, true /* controlledByApp */)));
     }
 
     msg->post();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 2f60072..c4bbcdf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -287,8 +287,9 @@
             // fall through
 
         case STATE_PAUSED:
+            mState = STATE_STOPPED;
             notifyListener_l(MEDIA_STOPPED);
-            // fall through
+            break;
 
         case STATE_PREPARED:
         case STATE_STOPPED:
@@ -314,6 +315,8 @@
             return OK;
 
         case STATE_RUNNING:
+            setPauseStartedTimeIfNeeded();
+            mState = STATE_PAUSED;
             notifyListener_l(MEDIA_PAUSED);
             mPlayer->pause();
             break;
@@ -322,9 +325,6 @@
             return INVALID_OPERATION;
     }
 
-    setPauseStartedTimeIfNeeded();
-    mState = STATE_PAUSED;
-
     return OK;
 }
 
@@ -675,15 +675,17 @@
     mAsyncResult = err;
 
     if (err == OK) {
+        // update state before notifying client, so that if client calls back into NuPlayerDriver
+        // in response, NuPlayerDriver has the right state
+        mState = STATE_PREPARED;
         if (mIsAsyncPrepare) {
             notifyListener_l(MEDIA_PREPARED);
         }
-        mState = STATE_PREPARED;
     } else {
+        mState = STATE_UNPREPARED;
         if (mIsAsyncPrepare) {
             notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
         }
-        mState = STATE_UNPREPARED;
     }
 
     mCondition.broadcast();
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 7ac2c0c..fd28ea1 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -1068,6 +1068,9 @@
 
     // compute everything we need...
     int countActiveTracks = 0;
+    // TODO: fix all16BitsStereNoResample logic to
+    // either properly handle muted tracks (it should ignore them)
+    // or remove altogether as an obsolete optimization.
     bool all16BitsStereoNoResample = true;
     bool resampling = false;
     bool volumeRamp = false;
@@ -1152,8 +1155,15 @@
                 if (countActiveTracks == 1) {
                     const int i = 31 - __builtin_clz(state->enabledTracks);
                     track_t& t = state->tracks[i];
-                    state->hook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
-                            t.mMixerChannelCount, t.mMixerInFormat, t.mMixerFormat);
+                    if ((t.needs & NEEDS_MUTE) == 0) {
+                        // The check prevents a muted track from acquiring a process hook.
+                        //
+                        // This is dangerous if the track is MONO as that requires
+                        // special case handling due to implicit channel duplication.
+                        // Stereo or Multichannel should actually be fine here.
+                        state->hook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
+                                t.mMixerChannelCount, t.mMixerInFormat, t.mMixerFormat);
+                    }
                 }
             }
         }
@@ -1188,6 +1198,7 @@
             if (countActiveTracks == 1) {
                 const int i = 31 - __builtin_clz(state->enabledTracks);
                 track_t& t = state->tracks[i];
+                // Muted single tracks handled by allMuted above.
                 state->hook = getProcessHook(PROCESSTYPE_NORESAMPLEONETRACK,
                         t.mMixerChannelCount, t.mMixerInFormat, t.mMixerFormat);
             }
@@ -1745,9 +1756,10 @@
         if (in == NULL || (((uintptr_t)in) & 3)) {
             memset(out, 0, numFrames
                     * t.mMixerChannelCount * audio_bytes_per_sample(t.mMixerFormat));
-            ALOGE_IF((((uintptr_t)in) & 3), "process stereo track: input buffer alignment pb: "
-                                              "buffer %p track %d, channels %d, needs %08x",
-                    in, i, t.channelCount, t.needs);
+            ALOGE_IF((((uintptr_t)in) & 3),
+                    "process__OneTrack16BitsStereoNoResampling: misaligned buffer"
+                    " %p track %d, channels %d, needs %08x, volume %08x vfl %f vfr %f",
+                    in, i, t.channelCount, t.needs, vrl, t.mVolume[0], t.mVolume[1]);
             return;
         }
         size_t outFrames = b.frameCount;
@@ -2173,6 +2185,10 @@
 
 /* Returns the proper process hook for mixing tracks. Currently works only for
  * PROCESSTYPE_NORESAMPLEONETRACK, a mix involving one track, no resampling.
+ *
+ * TODO: Due to the special mixing considerations of duplicating to
+ * a stereo output track, the input track cannot be MONO.  This should be
+ * prevented by the caller.
  */
 AudioMixer::process_hook_t AudioMixer::getProcessHook(int processType, uint32_t channelCount,
         audio_format_t mixerInFormat, audio_format_t mixerOutFormat)