Merge "Support querying active record sources" 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/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 7a6e344..0ab4e8c 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -65,10 +65,10 @@
status_t Camera2Client::checkPid(const char* checkLocation) const {
int callingPid = getCallingPid();
- if (callingPid == mClientPid || callingPid == mServicePid) return NO_ERROR;
+ if (callingPid == mClientPid) return NO_ERROR;
ALOGE("%s: attempt to use a locked camera from a different process"
- " (old pid %d, new pid %d, servicePid %d)", checkLocation, mClientPid, callingPid, mServicePid);
+ " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
return PERMISSION_DENIED;
}
@@ -139,19 +139,7 @@
mDestructionStarted = true;
- Parameters::State state;
- // warning:
- // holding on to locks more than necessary may be hazardous to your health
- {
- SharedParameters::Lock l(mParameters);
- state = l.mParameters.state;
- }
-
- if (state != Parameters::DISCONNECTED) {
- // Rewrite mClientPid to allow shutdown by CameraService
- mClientPid = getCallingPid();
- disconnect();
- }
+ disconnect();
ALOGI("Camera %d: Closed", mCameraId);
}
@@ -372,7 +360,10 @@
ATRACE_CALL();
Mutex::Autolock icl(mICameraLock);
status_t res;
- if ( (res = checkPid(__FUNCTION__) ) != OK) return;
+
+ // Allow both client and the media server to disconnect at all times
+ int callingPid = getCallingPid();
+ if (callingPid != mClientPid && callingPid != mServicePid) return;
if (mDevice == 0) return;
@@ -382,6 +373,7 @@
{
SharedParameters::Lock l(mParameters);
+ if (l.mParameters.state == Parameters::DISCONNECTED) return;
l.mParameters.state = Parameters::DISCONNECTED;
}
@@ -462,9 +454,13 @@
ALOGV("%s: Camera %d: Unlock call from pid %d; current client pid %d",
__FUNCTION__, mCameraId, getCallingPid(), mClientPid);
- // TODO: Check for uninterruptable conditions
-
if (mClientPid == getCallingPid()) {
+ SharedParameters::Lock l(mParameters);
+ if (l.mParameters.state == Parameters::RECORD ||
+ l.mParameters.state == Parameters::VIDEO_SNAPSHOT) {
+ ALOGD("Not allowed to unlock camera during recording.");
+ return INVALID_OPERATION;
+ }
mClientPid = 0;
mCameraClient.clear();
mSharedCameraClient.clear();
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
index 5b59ef9..b930c02 100644
--- a/services/camera/libcameraservice/CameraClient.cpp
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -73,6 +73,7 @@
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
+ mHardware.clear();
return NO_INIT;
}
@@ -101,8 +102,6 @@
int callingPid = getCallingPid();
LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this);
- // set mClientPid to let disconnet() tear down the hardware
- mClientPid = callingPid;
disconnect();
LOG1("CameraClient::~CameraClient X (pid %d, this %p)", callingPid, this);
}
@@ -124,7 +123,7 @@
status_t CameraClient::checkPid() const {
int callingPid = getCallingPid();
- if (callingPid == mClientPid || callingPid == mServicePid) return NO_ERROR;
+ if (callingPid == mClientPid) return NO_ERROR;
ALOGW("attempt to use a locked camera from a different process"
" (old pid %d, new pid %d)", mClientPid, callingPid);
@@ -218,7 +217,8 @@
LOG1("disconnect E (pid %d)", callingPid);
Mutex::Autolock lock(mLock);
- if (checkPid() != NO_ERROR) {
+ // Allow both client and the media server to disconnect at all times
+ if (callingPid != mClientPid && callingPid != mServicePid) {
ALOGW("different client - don't disconnect");
return;
}
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index 05494d3..3c679da 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -1739,9 +1739,6 @@
reqMeteringAreas, reqMeteringAreasSize);
if (res != OK) return res;
- res = request->update(ANDROID_CONTROL_AWB_REGIONS,
- reqMeteringAreas, reqMeteringAreasSize);
- if (res != OK) return res;
delete[] reqMeteringAreas;
/* don't include jpeg thumbnail size - it's valid for