Merge "Recent changes to the rtsp code require every buffer fed to the packet source to have a timestamp, we're ignoring timestamps for gtalk videochat but we still have to have a placeholder." into gingerbread
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index d0ed7df..362d9ee 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -73,8 +73,6 @@
 const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported";
 const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances";
 const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format";
-const char CameraParameters::KEY_METERING_MODE[] = "metering-mode";
-const char CameraParameters::KEY_SUPPORTED_METERING_MODES[] = "metering-mode-values";
 
 const char CameraParameters::TRUE[] = "true";
 const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity";
@@ -146,11 +144,6 @@
 const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
 const char CameraParameters::FOCUS_MODE_CONTINUOUS[] = "continuous";
 
-// Values for metering mode settings.
-const char CameraParameters::METERING_MODE_CENTER_WEIGHTED[] = "center-weighted";
-const char CameraParameters::METERING_MODE_FRAME_AVERAGE[] = "frame-average";
-const char CameraParameters::METERING_MODE_SPOT[] = "spot";
-
 CameraParameters::CameraParameters()
                 : mMap()
 {
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index a5c7874..7c5371a 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -286,13 +286,6 @@
     // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read only.
     static const char KEY_VIDEO_FRAME_FORMAT[];
 
-    // Metering mode. This affects how camera determines exposure.
-    // Example value: "spot" or METERING_MODE_XXX constants. Read/write.
-    static const char KEY_METERING_MODE[];
-    // Supported metering modes.
-    // Example value: "center-weighted,frame-average,spot". Read only.
-    static const char KEY_SUPPORTED_METERING_MODES[];
-
     // Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED.
     static const char TRUE[];
 
@@ -394,16 +387,6 @@
     // focus, applications should change the focus mode to other modes.
     static const char FOCUS_MODE_CONTINUOUS[];
 
-    // The camera determines the exposure by giving more weight to the
-    // central part of the scene.
-    static const char METERING_MODE_CENTER_WEIGHTED[];
-    // The camera determines the exposure by averaging the entire scene,
-    // giving no weighting to any particular area.
-    static const char METERING_MODE_FRAME_AVERAGE[];
-    // The camera determines the exposure by a very small area of the scene,
-    // typically the center.
-    static const char METERING_MODE_SPOT[];
-
 private:
     DefaultKeyedVector<String8,String8>    mMap;
 };
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 42a22b7..12f8f32 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -263,6 +263,10 @@
         }
     }
 
+    if (maxSocket == -1) {
+        return;
+    }
+
     int res = select(maxSocket + 1, &rs, NULL, NULL, &tv);
     CHECK_GE(res, 0);
 
@@ -292,6 +296,10 @@
              it != mStreams.end(); ++it) {
             StreamInfo *s = &*it;
 
+            if (s->mIsInjected) {
+                continue;
+            }
+
             if (s->mNumRTCPPacketsReceived == 0) {
                 // We have never received any RTCP packets on this stream,
                 // we don't even know where to send a report.
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index f20dd6f..ee6f65a 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -31,8 +31,6 @@
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/MediaErrors.h>
 
-#define USE_TCP_INTERLEAVED     0
-
 // If no access units are received within 3 secs, assume that the rtp
 // stream has ended and signal end of stream.
 static int64_t kAccessUnitTimeoutUs = 3000000ll;
@@ -83,7 +81,8 @@
           mFirstAccessUnit(true),
           mFirstAccessUnitNTP(0),
           mNumAccessUnitsReceived(0),
-          mCheckPending(false) {
+          mCheckPending(false),
+          mTryTCPInterleaving(false) {
         mNetLooper->setName("rtsp net");
         mNetLooper->start(false /* runOnCallingThread */,
                           false /* canCallJava */,
@@ -158,7 +157,13 @@
 
             case 'disc':
             {
-                (new AMessage('quit', id()))->post();
+                int32_t reconnect;
+                if (msg->findInt32("reconnect", &reconnect) && reconnect) {
+                    sp<AMessage> reply = new AMessage('conn', id());
+                    mConn->connect(mSessionURL.c_str(), reply);
+                } else {
+                    (new AMessage('quit', id()))->post();
+                }
                 break;
             }
 
@@ -325,10 +330,6 @@
 
                     parsePlayResponse(response);
 
-                    mDoneMsg->setInt32("result", OK);
-                    mDoneMsg->post();
-                    mDoneMsg = NULL;
-
                     sp<AMessage> timeout = new AMessage('tiou', id());
                     timeout->post(kStartupTimeoutUs);
                 } else {
@@ -342,12 +343,26 @@
             case 'abor':
             {
                 for (size_t i = 0; i < mTracks.size(); ++i) {
-                    mTracks.editItemAt(i).mPacketSource->signalEOS(
-                            ERROR_END_OF_STREAM);
+                    TrackInfo *info = &mTracks.editItemAt(i);
+
+                    info->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
+
+                    if (!info->mUsingInterleavedTCP) {
+                        mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket);
+
+                        close(info->mRTPSocket);
+                        close(info->mRTCPSocket);
+                    }
                 }
+                mTracks.clear();
 
                 sp<AMessage> reply = new AMessage('tear', id());
 
+                int32_t reconnect;
+                if (msg->findInt32("reconnect", &reconnect) && reconnect) {
+                    reply->setInt32("reconnect", true);
+                }
+
                 AString request;
                 request = "TEARDOWN ";
 
@@ -374,6 +389,12 @@
                      << result << " (" << strerror(-result) << ")";
 
                 sp<AMessage> reply = new AMessage('disc', id());
+
+                int32_t reconnect;
+                if (msg->findInt32("reconnect", &reconnect) && reconnect) {
+                    reply->setInt32("reconnect", true);
+                }
+
                 mConn->disconnect(reply);
                 break;
             }
@@ -414,6 +435,11 @@
                 size_t trackIndex;
                 CHECK(msg->findSize("track-index", &trackIndex));
 
+                if (trackIndex >= mTracks.size()) {
+                    LOG(ERROR) << "late packets ignored.";
+                    break;
+                }
+
                 TrackInfo *track = &mTracks.editItemAt(trackIndex);
 
                 int32_t eos;
@@ -457,6 +483,10 @@
                 }
 
                 if (mFirstAccessUnit) {
+                    mDoneMsg->setInt32("result", OK);
+                    mDoneMsg->post();
+                    mDoneMsg = NULL;
+
                     mFirstAccessUnit = false;
                     mFirstAccessUnitNTP = ntpTime;
                 }
@@ -583,8 +613,19 @@
             case 'tiou':
             {
                 if (mFirstAccessUnit) {
-                    LOG(WARNING) << "Never received any data, disconnecting.";
-                    (new AMessage('abor', id()))->post();
+                    if (mTryTCPInterleaving) {
+                        LOG(WARNING) << "Never received any data, disconnecting.";
+                        (new AMessage('abor', id()))->post();
+                    } else {
+                        LOG(WARNING)
+                            << "Never received any data, switching transports.";
+
+                        mTryTCPInterleaving = true;
+
+                        sp<AMessage> msg = new AMessage('abor', id());
+                        msg->setInt32("reconnect", true);
+                        msg->post();
+                    }
                 }
                 break;
             }
@@ -705,6 +746,7 @@
     uint64_t mFirstAccessUnitNTP;
     int64_t mNumAccessUnitsReceived;
     bool mCheckPending;
+    bool mTryTCPInterleaving;
 
     struct TrackInfo {
         AString mURL;
@@ -723,6 +765,7 @@
     void setupTrack(size_t index) {
         sp<APacketSource> source =
             new APacketSource(mSessionDesc, index);
+
         if (source->initCheck() != OK) {
             LOG(WARNING) << "Unsupported format. Ignoring track #"
                          << index << ".";
@@ -754,26 +797,26 @@
         request.append(trackURL);
         request.append(" RTSP/1.0\r\n");
 
-#if USE_TCP_INTERLEAVED
-        size_t interleaveIndex = 2 * (mTracks.size() - 1);
-        info->mUsingInterleavedTCP = true;
-        info->mRTPSocket = interleaveIndex;
-        info->mRTCPSocket = interleaveIndex + 1;
+        if (mTryTCPInterleaving) {
+            size_t interleaveIndex = 2 * (mTracks.size() - 1);
+            info->mUsingInterleavedTCP = true;
+            info->mRTPSocket = interleaveIndex;
+            info->mRTCPSocket = interleaveIndex + 1;
 
-        request.append("Transport: RTP/AVP/TCP;interleaved=");
-        request.append(interleaveIndex);
-        request.append("-");
-        request.append(interleaveIndex + 1);
-#else
-        unsigned rtpPort;
-        ARTPConnection::MakePortPair(
-                &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
+            request.append("Transport: RTP/AVP/TCP;interleaved=");
+            request.append(interleaveIndex);
+            request.append("-");
+            request.append(interleaveIndex + 1);
+        } else {
+            unsigned rtpPort;
+            ARTPConnection::MakePortPair(
+                    &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
 
-        request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
-        request.append(rtpPort);
-        request.append("-");
-        request.append(rtpPort + 1);
-#endif
+            request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
+            request.append(rtpPort);
+            request.append("-");
+            request.append(rtpPort + 1);
+        }
 
         request.append("\r\n");
 
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 1d87c0d..425ca31 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -133,7 +133,7 @@
         // request routing change if necessary
         uint32_t newDevice = getNewDevice(mHardwareOutput, false);
 #ifdef WITH_A2DP
-        checkOutputForAllStrategies(newDevice);
+        checkOutputForAllStrategies();
         // A2DP outputs must be closed after checkOutputForAllStrategies() is executed
         if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) {
             closeA2dpOutputs();
@@ -274,7 +274,7 @@
     // check for device and output changes triggered by new phone state
     newDevice = getNewDevice(mHardwareOutput, false);
 #ifdef WITH_A2DP
-    checkOutputForAllStrategies(newDevice);
+    checkOutputForAllStrategies();
     // suspend A2DP output if a SCO device is present.
     if (mA2dpOutput != 0 && mScoDeviceAddress != "") {
         if (oldState == AudioSystem::MODE_NORMAL) {
@@ -386,13 +386,28 @@
     // check for device and output changes triggered by new phone state
     uint32_t newDevice = getNewDevice(mHardwareOutput, false);
 #ifdef WITH_A2DP
-    checkOutputForAllStrategies(newDevice);
+    checkOutputForAllStrategies();
 #endif
     updateDeviceForStrategy();
     setOutputDevice(mHardwareOutput, newDevice);
     if (forceVolumeReeval) {
         applyStreamVolumes(mHardwareOutput, newDevice);
     }
+
+    audio_io_handle_t activeInput = getActiveInput();
+    if (activeInput != 0) {
+        AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
+        newDevice = getDeviceForInputSource(inputDesc->mInputSource);
+        if (newDevice != inputDesc->mDevice) {
+            LOGV("setForceUse() changing device from %x to %x for input %d",
+                    inputDesc->mDevice, newDevice, activeInput);
+            inputDesc->mDevice = newDevice;
+            AudioParameter param = AudioParameter();
+            param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
+            mpClientInterface->setParameters(activeInput, param.toString());
+        }
+    }
+
 }
 
 AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage)
@@ -1382,7 +1397,7 @@
     }
 }
 
-void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy, uint32_t &newDevice)
+void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy)
 {
     uint32_t prevDevice = getDeviceForStrategy(strategy);
     uint32_t curDevice = getDeviceForStrategy(strategy, false);
@@ -1401,12 +1416,6 @@
             LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy);
             srcOutput = mA2dpOutput;
         }
-
-        // do not change newDevice if it was already set before this call by a previous call to
-        // getNewDevice() or checkOutputForStrategy() for a strategy with higher priority
-        if (newDevice == 0 && mOutputs.valueFor(mHardwareOutput)->isUsedByStrategy(strategy)) {
-            newDevice = getDeviceForStrategy(strategy, false);
-        }
     }
     if (a2dpIsUsed && !a2dpWasUsed) {
         bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2);
@@ -1441,15 +1450,12 @@
     }
 }
 
-void AudioPolicyManagerBase::checkOutputForAllStrategies(uint32_t &newDevice)
+void AudioPolicyManagerBase::checkOutputForAllStrategies()
 {
-    // Check strategies in order of priority so that once newDevice is set
-    // for a given strategy it is not modified by subsequent calls to
-    // checkOutputForStrategy()
-    checkOutputForStrategy(STRATEGY_PHONE, newDevice);
-    checkOutputForStrategy(STRATEGY_SONIFICATION, newDevice);
-    checkOutputForStrategy(STRATEGY_MEDIA, newDevice);
-    checkOutputForStrategy(STRATEGY_DTMF, newDevice);
+    checkOutputForStrategy(STRATEGY_PHONE);
+    checkOutputForStrategy(STRATEGY_SONIFICATION);
+    checkOutputForStrategy(STRATEGY_MEDIA);
+    checkOutputForStrategy(STRATEGY_DTMF);
 }
 
 #endif