Merge "Camera: Clear Hardware device pointer when initialization fails" into jb-mr1-dev
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index d856bac..8ab9abe 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -36,6 +36,8 @@
 #include <arpa/inet.h>
 #include <cutils/properties.h>
 
+#include <ctype.h>
+
 namespace android {
 
 WifiDisplaySource::WifiDisplaySource(
@@ -46,6 +48,7 @@
       mClient(client),
       mSessionID(0),
       mStopReplyID(0),
+      mChosenRTPPort(-1),
       mUsingPCMAudio(false),
       mClientSessionID(0),
       mReaperPending(false),
@@ -532,11 +535,6 @@
         transportString = "TCP";
     }
 
-    if (property_get("media.wfd.use-pcm-audio", val, NULL)
-            && (!strcasecmp("true", val) || !strcmp("1", val))) {
-        ALOGI("Using PCM audio.");
-        mUsingPCMAudio = true;
-    }
     // For 720p60:
     //   use "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n"
     // For 720p30:
@@ -548,11 +546,11 @@
         "28 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none none\r\n"
         "wfd_audio_codecs: %s\r\n"
         "wfd_presentation_URL: rtsp://%s/wfd1.0/streamid=0 none\r\n"
-        "wfd_client_rtp_ports: RTP/AVP/%s;unicast 19000 0 mode=play\r\n",
+        "wfd_client_rtp_ports: RTP/AVP/%s;unicast %d 0 mode=play\r\n",
         (mUsingPCMAudio
             ? "LPCM 00000002 00" // 2 ch PCM 48kHz
             : "AAC 00000001 00"),  // 2 ch AAC 48kHz
-        mClientInfo.mLocalIP.c_str(), transportString.c_str());
+        mClientInfo.mLocalIP.c_str(), transportString.c_str(), mChosenRTPPort);
 
     AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n";
     AppendCommonResponse(&request, mNextCSeq);
@@ -649,6 +647,36 @@
     return OK;
 }
 
+// sink_audio_list := ("LPCM"|"AAC"|"AC3" HEXDIGIT*8 HEXDIGIT*2)
+//                       (", " sink_audio_list)*
+static void GetAudioModes(const char *s, const char *prefix, uint32_t *modes) {
+    *modes = 0;
+
+    size_t prefixLen = strlen(prefix);
+
+    while (*s != '0') {
+        if (!strncmp(s, prefix, prefixLen) && s[prefixLen] == ' ') {
+            unsigned latency;
+            if (sscanf(&s[prefixLen + 1], "%08x %02x", modes, &latency) != 2) {
+                *modes = 0;
+            }
+
+            return;
+        }
+
+        char *commaPos = strchr(s, ',');
+        if (commaPos != NULL) {
+            s = commaPos + 1;
+
+            while (isspace(*s)) {
+                ++s;
+            }
+        } else {
+            break;
+        }
+    }
+}
+
 status_t WifiDisplaySource::onReceiveM3Response(
         int32_t sessionID, const sp<ParsedMessage> &msg) {
     int32_t statusCode;
@@ -667,8 +695,63 @@
         return ERROR_MALFORMED;
     }
 
-#if REQUIRE_HDCP
     AString value;
+    if (!params->findParameter("wfd_client_rtp_ports", &value)) {
+        ALOGE("Sink doesn't report its choice of wfd_client_rtp_ports.");
+        return ERROR_MALFORMED;
+    }
+
+    unsigned port0, port1;
+    if (sscanf(value.c_str(),
+               "RTP/AVP/UDP;unicast %u %u mode=play",
+               &port0,
+               &port1) != 2
+        || port0 == 0 || port0 > 65535 || port1 != 0) {
+        ALOGE("Sink chose its wfd_client_rtp_ports poorly (%s)",
+              value.c_str());
+
+        return ERROR_MALFORMED;
+    }
+
+    mChosenRTPPort = port0;
+
+    if (!params->findParameter("wfd_audio_codecs", &value)) {
+        ALOGE("Sink doesn't report its choice of wfd_audio_codecs.");
+        return ERROR_MALFORMED;
+    }
+
+    if  (value == "none") {
+        ALOGE("Sink doesn't support audio at all.");
+        return ERROR_UNSUPPORTED;
+    }
+
+    uint32_t modes;
+    GetAudioModes(value.c_str(), "AAC", &modes);
+
+    bool supportsAAC = (modes & 1) != 0;  // AAC 2ch 48kHz
+
+    GetAudioModes(value.c_str(), "LPCM", &modes);
+
+    bool supportsPCM = (modes & 2) != 0;  // LPCM 2ch 48kHz
+
+    char val[PROPERTY_VALUE_MAX];
+    if (supportsPCM
+            && property_get("media.wfd.use-pcm-audio", val, NULL)
+            && (!strcasecmp("true", val) || !strcmp("1", val))) {
+        ALOGI("Using PCM audio.");
+        mUsingPCMAudio = true;
+    } else if (supportsAAC) {
+        ALOGI("Using AAC audio.");
+        mUsingPCMAudio = false;
+    } else if (supportsPCM) {
+        ALOGI("Using PCM audio.");
+        mUsingPCMAudio = true;
+    } else {
+        ALOGI("Sink doesn't support an audio format we do.");
+        return ERROR_UNSUPPORTED;
+    }
+
+#if REQUIRE_HDCP
     if (!params->findParameter("wfd_content_protection", &value)) {
         ALOGE("Sink doesn't appear to support content protection.");
         return -EACCES;
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 0692cde..9e748dd 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -114,6 +114,8 @@
 
     uint32_t mStopReplyID;
 
+    int32_t mChosenRTPPort;  // extracted from "wfd_client_rtp_ports"
+
     bool mUsingPCMAudio;
     int32_t mClientSessionID;
 
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index 199e525..05494d3 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -271,6 +271,10 @@
             jpegRotation);
 
     gpsEnabled = false;
+    gpsCoordinates[0] = 0.0;
+    gpsCoordinates[1] = 0.0;
+    gpsCoordinates[2] = 0.0;
+    gpsTimestamp = 0;
     gpsProcessingMethod = "unknown";
     // GPS fields in CameraParameters are not set by implementation
 
@@ -742,12 +746,14 @@
     params.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
             CameraParameters::PIXEL_FORMAT_ANDROID_OPAQUE);
 
+    recordingHint = false;
     params.set(CameraParameters::KEY_RECORDING_HINT,
             CameraParameters::FALSE);
 
     params.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED,
             CameraParameters::TRUE);
 
+    videoStabilization = false;
     params.set(CameraParameters::KEY_VIDEO_STABILIZATION,
             CameraParameters::FALSE);
 
@@ -772,10 +778,12 @@
     enableFocusMoveMessages = false;
     afTriggerCounter = 1;
     currentAfTriggerId = -1;
+    afInMotion = false;
 
     precaptureTriggerCounter = 1;
 
     previewCallbackFlags = 0;
+    previewCallbackOneShot = false;
 
     char value[PROPERTY_VALUE_MAX];
     property_get("camera.disable_zsl_mode", value, "0");