Merge "Spatializer: Workaround for Head Tracking on BT AAC" into tm-qpr-dev
diff --git a/media/libheadtracking/SensorPoseProvider.cpp b/media/libheadtracking/SensorPoseProvider.cpp
index bd8af04..3dee40a 100644
--- a/media/libheadtracking/SensorPoseProvider.cpp
+++ b/media/libheadtracking/SensorPoseProvider.cpp
@@ -122,6 +122,7 @@
~SensorPoseProviderImpl() override {
// Disable all active sensors.
mEnabledSensors.clear();
+ mQuit = true;
mLooper->wake();
mThread.join();
}
@@ -217,6 +218,7 @@
std::optional<int32_t> discontinuityCount;
};
+ bool mQuit = false;
sp<Looper> mLooper;
Listener* const mListener;
SensorManager* const mSensorManager;
@@ -260,13 +262,14 @@
initFinished(true);
- while (true) {
+ while (!mQuit) {
int ret = mLooper->pollOnce(-1 /* no timeout */, nullptr, nullptr, nullptr);
switch (ret) {
case ALOOPER_POLL_WAKE:
- // Normal way to exit.
- return;
+ // Continue to see if mQuit flag is set.
+ // This can be spurious (due to bugreport being taken).
+ continue;
case kIdent:
// Possible events on our queue.
@@ -285,7 +288,8 @@
ssize_t size = mQueue->filterEvents(&event, actual);
if (size < 0 || size > 1) {
- ALOGE("Unexpected return value from SensorEventQueue::filterEvents: %zd", size);
+ ALOGE("%s: Unexpected return value from SensorEventQueue::filterEvents: %zd",
+ __func__, size);
break;
}
if (size == 0) {
@@ -295,6 +299,7 @@
handleEvent(event);
}
+ ALOGD("%s: Exiting sensor event loop", __func__);
}
void handleEvent(const ASensorEvent& event) {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index a0bc8ca..6497b58 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -129,6 +129,7 @@
mRTPCVOExtMap(-1),
mRTPCVODegrees(0),
mRTPSockDscp(0),
+ mRTPSockOptEcn(0),
mRTPSockNetwork(0),
mLastSeqNo(0),
mStarted(false),
@@ -910,6 +911,13 @@
return OK;
}
+status_t StagefrightRecorder::setParamRtpEcn(int32_t ecn) {
+ ALOGV("setParamRtpEcn: %d", ecn);
+
+ mRTPSockOptEcn = ecn;
+ return OK;
+}
+
status_t StagefrightRecorder::requestIDRFrame() {
status_t ret = BAD_VALUE;
if (mVideoEncoderSource != NULL) {
@@ -1091,6 +1099,11 @@
if (safe_strtoi32(value.string(), &dscp)) {
return setParamRtpDscp(dscp);
}
+ } else if (key == "rtp-param-set-socket-ecn") {
+ int32_t targetEcn;
+ if (safe_strtoi32(value.string(), &targetEcn)) {
+ return setParamRtpEcn(targetEcn);
+ }
} else if (key == "rtp-param-set-socket-network") {
int64_t networkHandle;
if (safe_strtoi64(value.string(), &networkHandle)) {
@@ -1272,6 +1285,9 @@
if (mRTPSockDscp > 0) {
meta->setInt32(kKeyRtpDscp, mRTPSockDscp);
}
+ if (mRTPSockOptEcn > 0) {
+ meta->setInt32(kKeyRtpEcn, mRTPSockOptEcn);
+ }
status = mWriter->start(meta.get());
break;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index d7785da..0801101 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -153,6 +153,7 @@
int32_t mRTPCVOExtMap;
int32_t mRTPCVODegrees;
int32_t mRTPSockDscp;
+ int32_t mRTPSockOptEcn;
int64_t mRTPSockNetwork;
uint32_t mLastSeqNo;
@@ -247,6 +248,7 @@
status_t setRTPCVOExtMap(int32_t extmap);
status_t setRTPCVODegrees(int32_t cvoDegrees);
status_t setParamRtpDscp(int32_t dscp);
+ status_t setParamRtpEcn(int32_t ecn);
status_t setSocketNetwork(int64_t networkHandle);
status_t requestIDRFrame();
void clipVideoBitRate();
diff --git a/media/libmediaplayerservice/nuplayer/RTPSource.cpp b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
index 6a17972..fd03150 100644
--- a/media/libmediaplayerservice/nuplayer/RTPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTPSource.cpp
@@ -115,7 +115,7 @@
int sockRtp, sockRtcp;
ARTPConnection::MakeRTPSocketPair(&sockRtp, &sockRtcp, info->mLocalIp, info->mRemoteIp,
- info->mLocalPort, info->mRemotePort, info->mSocketNetwork);
+ info->mLocalPort, info->mRemotePort, info->mSocketNetwork, info->mRtpSockOptEcn);
sp<AMessage> notify = new AMessage('accu', this);
@@ -125,6 +125,8 @@
mRTPConn->addStream(sockRtp, sockRtcp, desc, i + 1, notify, false);
mRTPConn->setSelfID(info->mSelfID);
mRTPConn->setStaticJitterTimeMs(info->mJbTimeMs);
+ mRTPConn->setRtpSockOptEcn(info->mRtpSockOptEcn);
+ mRTPConn->setIsIPv6(info->mLocalIp);
unsigned long PT;
AString formatDesc, formatParams;
@@ -719,6 +721,8 @@
} else if (key == "rtp-param-set-socket-network") {
int64_t networkHandle = atoll(value);
setSocketNetwork(networkHandle);
+ } else if (key == "rtp-param-set-socket-ecn") {
+ info->mRtpSockOptEcn = atoi(value);
} else if (key == "rtp-param-jitter-buffer-time") {
// clamping min at 40, max at 3000
info->mJbTimeMs = std::min(std::max(40, atoi(value)), 3000);
diff --git a/media/libmediaplayerservice/nuplayer/include/nuplayer/RTPSource.h b/media/libmediaplayerservice/nuplayer/include/nuplayer/RTPSource.h
index 7d9bb8f..b2afe86 100644
--- a/media/libmediaplayerservice/nuplayer/include/nuplayer/RTPSource.h
+++ b/media/libmediaplayerservice/nuplayer/include/nuplayer/RTPSource.h
@@ -121,6 +121,8 @@
uint32_t mSelfID;
/* extmap:<value> for CVO will be set to here */
int32_t mCVOExtMap;
+ /* To check ECN is supported or not */
+ int32_t mRtpSockOptEcn;
/* a copy of TrackInfo in RTSPSource */
sp<AnotherPacketSource> mSource;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 88c1f3f..31faafb 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -267,6 +267,7 @@
kKeyRtpExtMap = 'extm', // int32_t, rtp extension ID for cvo on RTP protocol.
kKeyRtpCvoDegrees = 'cvod', // int32_t, rtp cvo degrees as per 3GPP 26.114.
kKeyRtpDscp = 'dscp', // int32_t, DSCP(Differentiated services codepoint) of RFC 2474.
+ kKeyRtpEcn = 'sEcn', // int32_t, ECN (Explicit Congestion Notification) of RFC 3168
kKeySocketNetwork = 'sNet', // int64_t, socket will be bound to network handle.
// Slow-motion markers
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a61f48f..165c336 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -16,6 +16,12 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "ARTPConnection"
+#define INET_ECN_NOT_ECT 0x00 /* ECN was not enabled */
+#define INET_ECN_ECT_1 0x01 /* ECN capable packet */
+#define INET_ECN_ECT_0 0x02 /* ECN capable packet */
+#define INET_ECN_CE 0x03 /* ECN congestion */
+#define INET_ECN_MASK 0x03 /* Mask of ECN bits */
+
#include <utils/Log.h>
#include <media/stagefright/rtsp/ARTPAssembler.h>
@@ -56,6 +62,7 @@
// static
const int64_t ARTPConnection::kSelectTimeoutUs = 1000LL;
+const int64_t ARTPConnection::kMinOneSecondNotifyDelayUs = 100000ll;
struct ARTPConnection::StreamInfo {
bool isIPv6;
@@ -84,7 +91,10 @@
mPollEventPending(false),
mLastReceiverReportTimeUs(-1),
mLastBitrateReportTimeUs(-1),
+ mLastCongestionNotifyTimeUs(-1),
mTargetBitrate(-1),
+ mRtpSockOptEcn(0),
+ mIsIPv6(false),
mStaticJitterTimeMs(kStaticJitterTimeMs) {
}
@@ -175,7 +185,7 @@
// static
void ARTPConnection::MakeRTPSocketPair(
int *rtpSocket, int *rtcpSocket, const char *localIp, const char *remoteIp,
- unsigned localPort, unsigned remotePort, int64_t socketNetwork) {
+ unsigned localPort, unsigned remotePort, int64_t socketNetwork, int32_t sockOptEcn) {
bool isIPv6 = false;
if (strchr(localIp, ':') != NULL)
isIPv6 = true;
@@ -204,6 +214,24 @@
}
}
+ if (sockOptEcn != 0) {
+ int sockOptForTOS = 1;
+ if (setsockopt(*rtpSocket, isIPv6 ? IPPROTO_IPV6 : IPPROTO_IP,
+ isIPv6 ? IPV6_RECVTCLASS : IP_RECVTOS,
+ (int *)&sockOptForTOS, sizeof(sockOptForTOS)) < 0) {
+ ALOGE("failed to set recv sockopt TOS on rtpsock(%d). err=%s", *rtpSocket,
+ strerror(errno));
+ } else {
+ ALOGD("successfully set recv sockopt TOS on rtpsock(%d)", *rtpSocket);
+ int result = setsockopt(*rtcpSocket, isIPv6 ? IPPROTO_IPV6 : IPPROTO_IP,
+ isIPv6 ? IPV6_RECVTCLASS : IP_RECVTOS,
+ (int *)&sockOptForTOS, sizeof(sockOptForTOS));
+ if (result >= 0) {
+ ALOGD("successfully set recv sockopt TOS on rtcpsock(%d).", *rtcpSocket);
+ }
+ }
+ }
+
bumpSocketBufferSize(*rtcpSocket);
struct sockaddr *addr;
@@ -593,32 +621,25 @@
sp<ABuffer> buffer = new ABuffer(65536);
- struct sockaddr *pRemoteRTCPAddr;
- int sizeSockSt;
- if (s->isIPv6) {
- pRemoteRTCPAddr = (struct sockaddr *)&s->mRemoteRTCPAddr6;
- sizeSockSt = sizeof(struct sockaddr_in6);
- } else {
- pRemoteRTCPAddr = (struct sockaddr *)&s->mRemoteRTCPAddr;
- sizeSockSt = sizeof(struct sockaddr_in);
- }
- socklen_t remoteAddrLen =
- (!receiveRTP && s->mNumRTCPPacketsReceived == 0)
- ? sizeSockSt : 0;
+ struct msghdr sMsg = {};
+ struct iovec sIov[1] = {};
- if (mFlags & kViLTEConnection) {
- remoteAddrLen = 0;
- }
+ sIov[0].iov_base = (char *) buffer->data();
+ sIov[0].iov_len = buffer->capacity();
+
+ sMsg.msg_iov = sIov;
+ sMsg.msg_iovlen = 1;
+
+ int cMsgSize = sizeof(struct cmsghdr) + sizeof(uint8_t);
+ char buf[CMSG_SPACE(cMsgSize)];
+ sMsg.msg_control = buf;
+ sMsg.msg_controllen = sizeof(buf);
+ sMsg.msg_flags = 0;
ssize_t nbytes;
do {
- nbytes = recvfrom(
- receiveRTP ? s->mRTPSocket : s->mRTCPSocket,
- buffer->data(),
- buffer->capacity(),
- 0,
- remoteAddrLen > 0 ? pRemoteRTCPAddr : NULL,
- remoteAddrLen > 0 ? &remoteAddrLen : NULL);
+ // Used recvmsg to get the TOS header of incoming packet
+ nbytes = recvmsg(receiveRTP ? s->mRTPSocket : s->mRTCPSocket, &sMsg, 0);
mCumulativeBytes += nbytes;
} while (nbytes < 0 && errno == EINTR);
@@ -633,6 +654,10 @@
}
}
+ if (nbytes > 0) {
+ handleIpHeadersIfReceived(s, sMsg);
+ }
+
buffer->setRange(0, nbytes);
// ALOGI("received %d bytes.", buffer->size());
@@ -647,13 +672,68 @@
return err;
}
+/* This function will check if TOS is present or not in received IP packet.
+ * After that if it is present then it will notify about congestion to upper
+ * layer if CE bit is set in TOS header.
+ **/
+void ARTPConnection::handleIpHeadersIfReceived(StreamInfo *s, struct msghdr sMsg) {
+ struct cmsghdr *cMsg;
+ cMsg = CMSG_FIRSTHDR(&sMsg);
+
+ if (cMsg == NULL) {
+ ALOGV("cmsg is null");
+ }
+
+ for (; cMsg != NULL; cMsg = CMSG_NXTHDR(&sMsg, cMsg)) {
+ bool isTOSHeader = ((cMsg->cmsg_level == (mIsIPv6 ? IPPROTO_IPV6 : IPPROTO_IP))
+ && (cMsg->cmsg_type == (mIsIPv6 ? IPV6_TCLASS : IP_TOS))
+ && (cMsg->cmsg_len));
+ if (isTOSHeader) {
+ uint8_t receivedTOS;
+ receivedTOS = *((uint8_t *) CMSG_DATA(cMsg));
+ // checking CE bit is set
+ bool isCEBitMarked = ((receivedTOS & INET_ECN_MASK) == INET_ECN_CE);
+
+ ALOGV("receivedTos(value -> %d)", receivedTOS);
+
+ if (isCEBitMarked) {
+ ALOGD("receivedTos(value -> %d), is ECN CE marked = %d",
+ receivedTOS, isCEBitMarked);
+ notifyCongestionToUpperLayerIfNeeded(s);
+ }
+ break;
+ }
+ }
+}
+
+/* this function will be use to notify congestion in video call to upper layer */
+void ARTPConnection::notifyCongestionToUpperLayerIfNeeded(StreamInfo *s) {
+ int64_t nowUs = ALooper::GetNowUs();
+
+ if (mLastCongestionNotifyTimeUs <= 0) {
+ mLastCongestionNotifyTimeUs = nowUs;
+ }
+
+ bool isNeedToUpdate = (mLastCongestionNotifyTimeUs + kMinOneSecondNotifyDelayUs <= nowUs);
+ ALOGD("ECN info set by upper layer=%d, isNeedToUpdate=%d", mRtpSockOptEcn, isNeedToUpdate);
+
+ if ((mRtpSockOptEcn != 0) && (isNeedToUpdate)) {
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("rtcp-event", 1);
+ notify->setInt32("payload-type", ARTPSource::RTP_QUALITY_CD);
+ notify->post();
+ mLastCongestionNotifyTimeUs = nowUs;
+ ALOGD("Congestion detected in n/w, Notify upper layer");
+ }
+}
+
ssize_t ARTPConnection::send(const StreamInfo *info, const sp<ABuffer> buffer) {
struct sockaddr* pRemoteRTCPAddr;
int sizeSockSt;
/* It seems this isIPv6 variable is useless.
* We should remove it to prevent confusion */
- if (info->isIPv6) {
+ if (mIsIPv6) {
pRemoteRTCPAddr = (struct sockaddr *)&info->mRemoteRTCPAddr6;
sizeSockSt = sizeof(struct sockaddr_in6);
} else {
@@ -1215,12 +1295,20 @@
mTargetBitrate = targetBitrate;
}
+void ARTPConnection::setRtpSockOptEcn(int32_t sockOptEcn) {
+ mRtpSockOptEcn = sockOptEcn;
+}
+
+void ARTPConnection::setIsIPv6(const char *localIp) {
+ mIsIPv6 = (strchr(localIp, ':') != nullptr);
+}
+
void ARTPConnection::checkRxBitrate(int64_t nowUs) {
if (mLastBitrateReportTimeUs <= 0) {
mCumulativeBytes = 0;
mLastBitrateReportTimeUs = nowUs;
}
- else if (mLastEarlyNotifyTimeUs + 100000ll <= nowUs) {
+ else if (mLastEarlyNotifyTimeUs + kMinOneSecondNotifyDelayUs <= nowUs) {
int32_t timeDiff = (nowUs - mLastBitrateReportTimeUs) / 1000000ll;
int32_t bitrate = mCumulativeBytes * 8 / timeDiff;
mLastEarlyNotifyTimeUs = nowUs;
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 8990f0c..41f2d67 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -255,9 +255,34 @@
if (params->findInt32(kKeyRtpCvoDegrees, &rtpCVODegrees))
mRTPCVODegrees = rtpCVODegrees;
+ bool needToSetSockOpt = false;
int32_t dscp = 0;
- if (params->findInt32(kKeyRtpDscp, &dscp))
- updateSocketDscp(dscp);
+ if (params->findInt32(kKeyRtpDscp, &dscp)) {
+ mRtpLayer3Dscp = dscp << 2;
+ needToSetSockOpt = true;
+ }
+
+ int32_t ecn = 0;
+ if (params->findInt32(kKeyRtpEcn, &ecn)) {
+ /*
+ * @ecn, possible value for ECN.
+ * +-----+-----+
+ * | ECN FIELD |
+ * +-----+-----+
+ * ECT CE [Obsolete] RFC 2481 names for the ECN bits.
+ * 0 0 Not-ECT
+ * 0 1 ECT (ECN-Capable Transport) (1)
+ * 1 0 ECT (ECN-Capable Transport) (0)
+ * 1 1 CE (Congestion Experienced)
+ *
+ */
+ mRtpSockOptEcn = ecn;
+ needToSetSockOpt = true;
+ }
+
+ if (needToSetSockOpt) {
+ updateSocketOpt();
+ }
int64_t sockNetwork = 0;
if (params->findInt64(kKeySocketNetwork, &sockNetwork))
@@ -1438,18 +1463,29 @@
mPayloadType = payloadType;
}
-void ARTPWriter::updateSocketDscp(int32_t dscp) {
- mRtpLayer3Dscp = dscp << 2;
+/*
+ * This function will set socket option in IP header
+ */
+void ARTPWriter::updateSocketOpt() {
+ /*
+ * 0 1 2 3 4 5 6 7
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | DS FIELD, DSCP | ECN FIELD |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ */
+ int sockOpt = mRtpLayer3Dscp ^ mRtpSockOptEcn;
+ ALOGD("Update socket opt with sockopt=%d, mRtpLayer3Dscp=%d, mRtpSockOptEcn=%d",
+ sockOpt, mRtpLayer3Dscp, mRtpSockOptEcn);
- /* mRtpLayer3Dscp will be mapped to WMM(Wifi) as per operator's requirement */
- if (setsockopt(mRTPSocket, IPPROTO_IP, IP_TOS,
- (int *)&mRtpLayer3Dscp, sizeof(mRtpLayer3Dscp)) < 0) {
- ALOGE("failed to set dscp on rtpsock. err=%s", strerror(errno));
+ /* sockOpt will be used to set socket option in IP header */
+ if (setsockopt(mRTPSocket, mIsIPv6 ? IPPROTO_IPV6 : IPPROTO_IP, mIsIPv6 ? IPV6_TCLASS : IP_TOS,
+ (int *)&sockOpt, sizeof(sockOpt)) < 0) {
+ ALOGE("failed to set sockopt on rtpsock. err=%s", strerror(errno));
} else {
- ALOGD("successfully set dscp on rtpsock. opt=%d", mRtpLayer3Dscp);
- setsockopt(mRTCPSocket, IPPROTO_IP, IP_TOS,
- (int *)&mRtpLayer3Dscp, sizeof(mRtpLayer3Dscp));
- ALOGD("successfully set dscp on rtcpsock. opt=%d", mRtpLayer3Dscp);
+ ALOGD("successfully set sockopt. opt=%d", sockOpt);
+ setsockopt(mRTCPSocket, mIsIPv6 ? IPPROTO_IPV6 : IPPROTO_IP, mIsIPv6 ? IPV6_TCLASS : IP_TOS,
+ (int *)&sockOpt, sizeof(sockOpt));
+ ALOGD("successfully set sockopt rtcpsock. opt=%d", sockOpt);
}
}
diff --git a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h
index 73d2866..250de71 100644
--- a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPConnection.h
@@ -20,6 +20,7 @@
#include <media/stagefright/foundation/AHandler.h>
#include <utils/List.h>
+#include <sys/socket.h>
namespace android {
@@ -48,6 +49,8 @@
void setSelfID(const uint32_t selfID);
void setStaticJitterTimeMs(const uint32_t jbTimeMs);
void setTargetBitrate(int32_t targetBitrate);
+ void setRtpSockOptEcn(int32_t sockOptEcn);
+ void setIsIPv6(const char *localIp);
// Creates a pair of UDP datagram sockets bound to adjacent ports
// (the rtpSocket is bound to an even port, the rtcpSocket to the
@@ -60,7 +63,8 @@
static void MakeRTPSocketPair(
int *rtpSocket, int *rtcpSocket,
const char *localIp, const char *remoteIp,
- unsigned localPort, unsigned remotePort, int64_t socketNetwork = 0);
+ unsigned localPort, unsigned remotePort, int64_t socketNetwork = 0,
+ int32_t sockOptEcn = 0);
protected:
virtual ~ARTPConnection();
@@ -77,6 +81,7 @@
};
static const int64_t kSelectTimeoutUs;
+ static const int64_t kMinOneSecondNotifyDelayUs;
uint32_t mFlags;
@@ -87,9 +92,12 @@
int64_t mLastReceiverReportTimeUs;
int64_t mLastBitrateReportTimeUs;
int64_t mLastEarlyNotifyTimeUs;
+ int64_t mLastCongestionNotifyTimeUs;
int32_t mSelfID;
int32_t mTargetBitrate;
+ int32_t mRtpSockOptEcn;
+ bool mIsIPv6;
uint32_t mStaticJitterTimeMs;
@@ -103,6 +111,8 @@
void onInjectPacket(const sp<AMessage> &msg);
void onSendReceiverReports();
void checkRxBitrate(int64_t nowUs);
+ void notifyCongestionToUpperLayerIfNeeded(StreamInfo *s);
+ void handleIpHeadersIfReceived(StreamInfo *s, struct msghdr sMsg);
status_t receive(StreamInfo *info, bool receiveRTP);
ssize_t send(const StreamInfo *info, const sp<ABuffer> buffer);
diff --git a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h
index e9b4942..3fa5713 100644
--- a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPSource.h
@@ -50,6 +50,7 @@
RTCP_FIRST_PACKET = 101,
RTP_QUALITY = 102,
RTP_QUALITY_EMC = 103,
+ RTP_QUALITY_CD = 104,
RTCP_SR = 200,
RTCP_RR = 201,
RTCP_TSFB = 205,
diff --git a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPWriter.h
index 2982cf6..ecd29d0 100644
--- a/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPWriter.h
+++ b/media/libstagefright/rtsp/include/media/stagefright/rtsp/ARTPWriter.h
@@ -50,7 +50,7 @@
virtual status_t pause();
void updateCVODegrees(int32_t cvoDegrees);
void updatePayloadType(int32_t payloadType);
- void updateSocketDscp(int32_t dscp);
+ void updateSocketOpt();
void updateSocketNetwork(int64_t socketNetwork);
uint32_t getSequenceNum();
virtual uint64_t getAccumulativeBytes() override;
@@ -98,6 +98,7 @@
struct sockaddr_in6 mRTPAddr6;
struct sockaddr_in6 mRTCPAddr6;
int32_t mRtpLayer3Dscp;
+ int32_t mRtpSockOptEcn;
net_handle_t mRTPSockNetwork;
AString mProfileLevel;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 4653f96..f94106f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -283,7 +283,6 @@
return opPackageLegacy == package; }) == packages.end()) {
ALOGW("The package name(%s) provided does not correspond to the uid %d",
attributionSource.packageName.value_or("").c_str(), attributionSource.uid);
- checkedAttributionSource.packageName = std::optional<std::string>();
}
}
return checkedAttributionSource;
@@ -582,6 +581,33 @@
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
audio_attributes_t localAttr = *attr;
+
+ // TODO b/182392553: refactor or make clearer
+ pid_t clientPid =
+ VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(client.attributionSource.pid));
+ bool updatePid = (clientPid == (pid_t)-1);
+ const uid_t callingUid = IPCThreadState::self()->getCallingUid();
+
+ AttributionSourceState adjAttributionSource = client.attributionSource;
+ if (!isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
+ uid_t clientUid =
+ VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(client.attributionSource.uid));
+ ALOGW_IF(clientUid != callingUid,
+ "%s uid %d tried to pass itself off as %d",
+ __FUNCTION__, callingUid, clientUid);
+ adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
+ updatePid = true;
+ }
+ if (updatePid) {
+ const pid_t callingPid = IPCThreadState::self()->getCallingPid();
+ ALOGW_IF(clientPid != (pid_t)-1 && clientPid != callingPid,
+ "%s uid %d pid %d tried to pass itself off as pid %d",
+ __func__, callingUid, callingPid, clientPid);
+ adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
+ }
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource);
+
if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
audio_config_t fullConfig = AUDIO_CONFIG_INITIALIZER;
fullConfig.sample_rate = config->sample_rate;
@@ -591,7 +617,7 @@
bool isSpatialized;
ret = AudioSystem::getOutputForAttr(&localAttr, &io,
actualSessionId,
- &streamType, client.attributionSource,
+ &streamType, adjAttributionSource,
&fullConfig,
(audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ |
AUDIO_OUTPUT_FLAG_DIRECT),
@@ -602,7 +628,7 @@
ret = AudioSystem::getInputForAttr(&localAttr, &io,
RECORD_RIID_INVALID,
actualSessionId,
- client.attributionSource,
+ adjAttributionSource,
config,
AUDIO_INPUT_FLAG_MMAP_NOIRQ, deviceId, &portId);
}
@@ -1051,7 +1077,7 @@
audio_attributes_t localAttr = input.attr;
AttributionSourceState adjAttributionSource = input.clientInfo.attributionSource;
- if (!isAudioServerOrMediaServerUid(callingUid)) {
+ if (!isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
ALOGW_IF(clientUid != callingUid,
"%s uid %d tried to pass itself off as %d",
__FUNCTION__, callingUid, clientUid);
@@ -1067,6 +1093,8 @@
clientPid = callingPid;
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource);
audio_session_t sessionId = input.sessionId;
if (sessionId == AUDIO_SESSION_ALLOCATE) {
@@ -2273,7 +2301,7 @@
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
const uid_t currentUid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(
adjAttributionSource.uid));
- if (!isAudioServerOrMediaServerUid(callingUid)) {
+ if (!isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
ALOGW_IF(currentUid != callingUid,
"%s uid %d tried to pass itself off as %d",
__FUNCTION__, callingUid, currentUid);
@@ -2289,7 +2317,8 @@
__func__, callingUid, callingPid, currentPid);
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
}
-
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ adjAttributionSource);
// we don't yet support anything other than linear PCM
if (!audio_is_valid_format(input.config.format) || !audio_is_linear_pcm(input.config.format)) {
ALOGE("createRecord() invalid format %#x", input.config.format);
@@ -3906,7 +3935,7 @@
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
pid_t currentPid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(adjAttributionSource.pid));
- if (currentPid == -1 || !isAudioServerOrMediaServerUid(callingUid)) {
+ if (currentPid == -1 || !isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
const pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW_IF(currentPid != -1 && currentPid != callingPid,
"%s uid %d pid %d tried to pass itself off as pid %d",
@@ -3914,6 +3943,7 @@
adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
currentPid = callingPid;
}
+ adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(adjAttributionSource);
ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
adjAttributionSource.pid, effectClient.get(), priority, sessionId, io,
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 4ac24a9..211bf71 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8329,8 +8329,6 @@
audio_input_flags_t inputFlags = mInput->flags;
audio_input_flags_t requestedFlags = *flags;
uint32_t sampleRate;
- AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
- attributionSource);
lStatus = initCheck();
if (lStatus != NO_ERROR) {
@@ -8345,7 +8343,7 @@
}
if (maxSharedAudioHistoryMs != 0) {
- if (!captureHotwordAllowed(checkedAttributionSource)) {
+ if (!captureHotwordAllowed(attributionSource)) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
@@ -8466,16 +8464,16 @@
Mutex::Autolock _l(mLock);
int32_t startFrames = -1;
if (!mSharedAudioPackageName.empty()
- && mSharedAudioPackageName == checkedAttributionSource.packageName
+ && mSharedAudioPackageName == attributionSource.packageName
&& mSharedAudioSessionId == sessionId
- && captureHotwordAllowed(checkedAttributionSource)) {
+ && captureHotwordAllowed(attributionSource)) {
startFrames = mSharedAudioStartFrames;
}
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
- checkedAttributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
+ attributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
startFrames);
lStatus = track->initCheck();
@@ -10233,19 +10231,22 @@
void AudioFlinger::MmapThread::checkInvalidTracks_l()
{
+ sp<MmapStreamCallback> callback;
for (const sp<MmapTrack> &track : mActiveTracks) {
if (track->isInvalid()) {
- sp<MmapStreamCallback> callback = mCallback.promote();
- if (callback != 0) {
- mLock.unlock();
- callback->onTearDown(track->portId());
- mLock.lock();
- } else if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
- ALOGW("Could not notify MMAP stream tear down: no onTearDown callback!");
+ callback = mCallback.promote();
+ if (callback == nullptr && mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
+ ALOGW("Could not notify MMAP stream tear down: no onRoutingChanged callback!");
mNoCallbackWarningCount++;
}
+ break;
}
}
+ if (callback != 0) {
+ mLock.unlock();
+ callback->onRoutingChanged(AUDIO_PORT_HANDLE_NONE);
+ mLock.lock();
+ }
}
void AudioFlinger::MmapThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 0a1bc81..2a77d22 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -529,10 +529,7 @@
id, attr.flags);
return nullptr;
}
-
- AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
- attributionSource);
- return new OpPlayAudioMonitor(checkedAttributionSource, attr.usage, id);
+ return new OpPlayAudioMonitor(attributionSource, attr.usage, id);
}
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index df49bba..49224c5 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -352,31 +352,20 @@
ALOGV("%s()", __func__);
Mutex::Autolock _l(mLock);
- // TODO b/182392553: refactor or remove
- AttributionSourceState adjAttributionSource = attributionSource;
- const uid_t callingUid = IPCThreadState::self()->getCallingUid();
- if (!isAudioServerOrMediaServerUid(callingUid) || attributionSource.uid == -1) {
- int32_t callingUidAidl = VALUE_OR_RETURN_BINDER_STATUS(
- legacy2aidl_uid_t_int32_t(callingUid));
- ALOGW_IF(attributionSource.uid != -1 && attributionSource.uid != callingUidAidl,
- "%s uid %d tried to pass itself off as %d", __func__,
- callingUidAidl, attributionSource.uid);
- adjAttributionSource.uid = callingUidAidl;
- }
if (!mPackageManager.allowPlaybackCapture(VALUE_OR_RETURN_BINDER_STATUS(
- aidl2legacy_int32_t_uid_t(adjAttributionSource.uid)))) {
+ aidl2legacy_int32_t_uid_t(attributionSource.uid)))) {
attr.flags = static_cast<audio_flags_mask_t>(attr.flags | AUDIO_FLAG_NO_MEDIA_PROJECTION);
}
if (((attr.flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
- && !bypassInterruptionPolicyAllowed(adjAttributionSource)) {
+ && !bypassInterruptionPolicyAllowed(attributionSource)) {
attr.flags = static_cast<audio_flags_mask_t>(
attr.flags & ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE));
}
if (attr.content_type == AUDIO_CONTENT_TYPE_ULTRASOUND) {
- if (!accessUltrasoundAllowed(adjAttributionSource)) {
+ if (!accessUltrasoundAllowed(attributionSource)) {
ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
- __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ __func__, attributionSource.uid, attributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
}
@@ -386,7 +375,7 @@
bool isSpatialized = false;
status_t result = mAudioPolicyManager->getOutputForAttr(&attr, &output, session,
&stream,
- adjAttributionSource,
+ attributionSource,
&config,
&flags, &selectedDeviceId, &portId,
&secondaryOutputs,
@@ -401,20 +390,20 @@
break;
case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
if (((attr.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0)
- && !callAudioInterceptionAllowed(adjAttributionSource)) {
+ && !callAudioInterceptionAllowed(attributionSource)) {
ALOGE("%s() permission denied: call redirection not allowed for uid %d",
- __func__, adjAttributionSource.uid);
+ __func__, attributionSource.uid);
result = PERMISSION_DENIED;
- } else if (!modifyPhoneStateAllowed(adjAttributionSource)) {
+ } else if (!modifyPhoneStateAllowed(attributionSource)) {
ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
- __func__, adjAttributionSource.uid);
+ __func__, attributionSource.uid);
result = PERMISSION_DENIED;
}
break;
case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
- if (!modifyAudioRoutingAllowed(adjAttributionSource)) {
+ if (!modifyAudioRoutingAllowed(attributionSource)) {
ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
- __func__, adjAttributionSource.uid);
+ __func__, attributionSource.uid);
result = PERMISSION_DENIED;
}
break;
@@ -427,7 +416,7 @@
if (result == NO_ERROR) {
sp<AudioPlaybackClient> client =
- new AudioPlaybackClient(attr, output, adjAttributionSource, session,
+ new AudioPlaybackClient(attr, output, attributionSource, session,
portId, selectedDeviceId, stream, isSpatialized);
mAudioPlaybackClients.add(portId, client);
@@ -613,33 +602,8 @@
return binderStatusFromStatusT(BAD_VALUE);
}
- // Make sure attribution source represents the current caller
- AttributionSourceState adjAttributionSource = attributionSource;
- // TODO b/182392553: refactor or remove
- bool updatePid = (attributionSource.pid == -1);
- const uid_t callingUid =IPCThreadState::self()->getCallingUid();
- const uid_t currentUid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(
- attributionSource.uid));
- if (!isAudioServerOrMediaServerUid(callingUid)) {
- ALOGW_IF(currentUid != (uid_t)-1 && currentUid != callingUid,
- "%s uid %d tried to pass itself off as %d", __FUNCTION__, callingUid,
- currentUid);
- adjAttributionSource.uid = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_uid_t_int32_t(
- callingUid));
- updatePid = true;
- }
-
- if (updatePid) {
- const int32_t callingPid = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_pid_t_int32_t(
- IPCThreadState::self()->getCallingPid()));
- ALOGW_IF(attributionSource.pid != -1 && attributionSource.pid != callingPid,
- "%s uid %d pid %d tried to pass itself off as pid %d",
- __func__, adjAttributionSource.uid, callingPid, attributionSource.pid);
- adjAttributionSource.pid = callingPid;
- }
-
RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(validateUsage(attr,
- adjAttributionSource)));
+ attributionSource)));
// check calling permissions.
// Capturing from the following sources does not require permission RECORD_AUDIO
@@ -650,17 +614,17 @@
// type is API_INPUT_MIX_EXT_POLICY_REROUTE and by AudioService if a media projection
// is used and input type is API_INPUT_MIX_PUBLIC_CAPTURE_PLAYBACK
// - ECHO_REFERENCE source is controlled by captureAudioOutputAllowed()
- if (!(recordingAllowed(adjAttributionSource, inputSource)
+ if (!(recordingAllowed(attributionSource, inputSource)
|| inputSource == AUDIO_SOURCE_FM_TUNER
|| inputSource == AUDIO_SOURCE_REMOTE_SUBMIX
|| inputSource == AUDIO_SOURCE_ECHO_REFERENCE)) {
ALOGE("%s permission denied: recording not allowed for %s",
- __func__, adjAttributionSource.toString().c_str());
+ __func__, attributionSource.toString().c_str());
return binderStatusFromStatusT(PERMISSION_DENIED);
}
- bool canCaptureOutput = captureAudioOutputAllowed(adjAttributionSource);
- bool canInterceptCallAudio = callAudioInterceptionAllowed(adjAttributionSource);
+ bool canCaptureOutput = captureAudioOutputAllowed(attributionSource);
+ bool canInterceptCallAudio = callAudioInterceptionAllowed(attributionSource);
bool isCallAudioSource = inputSource == AUDIO_SOURCE_VOICE_UPLINK
|| inputSource == AUDIO_SOURCE_VOICE_DOWNLINK
|| inputSource == AUDIO_SOURCE_VOICE_CALL;
@@ -674,11 +638,11 @@
}
if (inputSource == AUDIO_SOURCE_FM_TUNER
&& !canCaptureOutput
- && !captureTunerAudioInputAllowed(adjAttributionSource)) {
+ && !captureTunerAudioInputAllowed(attributionSource)) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
- bool canCaptureHotword = captureHotwordAllowed(adjAttributionSource);
+ bool canCaptureHotword = captureHotwordAllowed(attributionSource);
if ((inputSource == AUDIO_SOURCE_HOTWORD) && !canCaptureHotword) {
return binderStatusFromStatusT(PERMISSION_DENIED);
}
@@ -686,14 +650,14 @@
if (((flags & AUDIO_INPUT_FLAG_HW_HOTWORD) != 0)
&& !canCaptureHotword) {
ALOGE("%s: permission denied: hotword mode not allowed"
- " for uid %d pid %d", __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ " for uid %d pid %d", __func__, attributionSource.uid, attributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
if (attr.source == AUDIO_SOURCE_ULTRASOUND) {
- if (!accessUltrasoundAllowed(adjAttributionSource)) {
+ if (!accessUltrasoundAllowed(attributionSource)) {
ALOGE("%s: permission denied: ultrasound not allowed for uid %d pid %d",
- __func__, adjAttributionSource.uid, adjAttributionSource.pid);
+ __func__, attributionSource.uid, attributionSource.pid);
return binderStatusFromStatusT(PERMISSION_DENIED);
}
}
@@ -708,7 +672,7 @@
AutoCallerClear acc;
// the audio_in_acoustics_t parameter is ignored by get_input()
status = mAudioPolicyManager->getInputForAttr(&attr, &input, riid, session,
- adjAttributionSource, &config,
+ attributionSource, &config,
flags, &selectedDeviceId,
&inputType, &portId);
@@ -737,7 +701,7 @@
}
break;
case AudioPolicyInterface::API_INPUT_MIX_EXT_POLICY_REROUTE:
- if (!(modifyAudioRoutingAllowed(adjAttributionSource)
+ if (!(modifyAudioRoutingAllowed(attributionSource)
|| ((attr.flags & AUDIO_FLAG_CALL_REDIRECTION) != 0
&& canInterceptCallAudio))) {
ALOGE("%s permission denied for remote submix capture", __func__);
@@ -760,7 +724,7 @@
}
sp<AudioRecordClient> client = new AudioRecordClient(attr, input, session, portId,
- selectedDeviceId, adjAttributionSource,
+ selectedDeviceId, attributionSource,
canCaptureOutput, canCaptureHotword,
mOutputCommandThread);
mAudioRecordClients.add(portId, client);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a78112d..1115920 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -203,6 +203,7 @@
status_t res;
std::vector<std::string> deviceIds;
+ std::unordered_map<std::string, std::set<std::string>> unavailPhysicalIds;
{
Mutex::Autolock l(mServiceLock);
@@ -233,7 +234,7 @@
ALOGE("Failed to enumerate flash units: %s (%d)", strerror(-res), res);
}
- deviceIds = mCameraProviderManager->getCameraDeviceIds();
+ deviceIds = mCameraProviderManager->getCameraDeviceIds(&unavailPhysicalIds);
}
@@ -242,6 +243,12 @@
if (getCameraState(id8) == nullptr) {
onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
}
+ if (unavailPhysicalIds.count(cameraId) > 0) {
+ for (const auto& physicalId : unavailPhysicalIds[cameraId]) {
+ String8 physicalId8 = String8(physicalId.c_str());
+ onDeviceStatusChanged(id8, physicalId8, CameraDeviceStatus::NOT_PRESENT);
+ }
+ }
}
// Derive primary rear/front cameras, and filter their charactierstics.
@@ -495,7 +502,7 @@
if (state == nullptr) {
ALOGE("%s: Physical camera id %s status change on a non-present ID %s",
- __FUNCTION__, id.string(), physicalId.string());
+ __FUNCTION__, physicalId.string(), id.string());
return;
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 6ef16b3..0f2100b 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -197,12 +197,17 @@
return std::make_pair(systemCameraCount, publicCameraCount);
}
-std::vector<std::string> CameraProviderManager::getCameraDeviceIds() const {
+std::vector<std::string> CameraProviderManager::getCameraDeviceIds(std::unordered_map<
+ std::string, std::set<std::string>>* unavailablePhysicalIds) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
std::vector<std::string> deviceIds;
for (auto& provider : mProviders) {
for (auto& id : provider->mUniqueCameraIds) {
deviceIds.push_back(id);
+ if (unavailablePhysicalIds != nullptr &&
+ provider->mUnavailablePhysicalCameras.count(id) > 0) {
+ (*unavailablePhysicalIds)[id] = provider->mUnavailablePhysicalCameras.at(id);
+ }
}
}
return deviceIds;
@@ -839,9 +844,6 @@
void CameraProviderManager::ProviderInfo::initializeProviderInfoCommon(
const std::vector<std::string> &devices) {
-
- sp<StatusListener> listener = mManager->getStatusListener();
-
for (auto& device : devices) {
std::string id;
status_t res = addDevice(device, CameraDeviceStatus::PRESENT, &id);
@@ -856,38 +858,22 @@
mProviderName.c_str(), mDevices.size());
// Process cached status callbacks
- std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus =
- std::make_unique<std::vector<CameraStatusInfoT>>();
{
std::lock_guard<std::mutex> lock(mInitLock);
for (auto& statusInfo : mCachedStatus) {
std::string id, physicalId;
- status_t res = OK;
if (statusInfo.isPhysicalCameraStatus) {
- res = physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
+ physicalCameraDeviceStatusChangeLocked(&id, &physicalId,
statusInfo.cameraId, statusInfo.physicalCameraId, statusInfo.status);
} else {
- res = cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
- }
- if (res == OK) {
- cachedStatus->emplace_back(statusInfo.isPhysicalCameraStatus,
- id.c_str(), physicalId.c_str(), statusInfo.status);
+ cameraDeviceStatusChangeLocked(&id, statusInfo.cameraId, statusInfo.status);
}
}
mCachedStatus.clear();
mInitialized = true;
}
-
- // The cached status change callbacks cannot be fired directly from this
- // function, due to same-thread deadlock trying to acquire mInterfaceMutex
- // twice.
- if (listener != nullptr) {
- mInitialStatusCallbackFuture = std::async(std::launch::async,
- &CameraProviderManager::ProviderInfo::notifyInitialStatusChange, this,
- listener, std::move(cachedStatus));
- }
}
CameraProviderManager::ProviderInfo::DeviceInfo* CameraProviderManager::findDeviceInfoLocked(
@@ -1957,6 +1943,7 @@
for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
if ((*it)->mId == id) {
mUniqueCameraIds.erase(id);
+ mUnavailablePhysicalCameras.erase(id);
if ((*it)->isAPI1Compatible()) {
mUniqueAPI1CompatibleCameraIds.erase(std::remove(
mUniqueAPI1CompatibleCameraIds.begin(),
@@ -2224,6 +2211,15 @@
return BAD_VALUE;
}
+ if (mUnavailablePhysicalCameras.count(cameraId) == 0) {
+ mUnavailablePhysicalCameras.emplace(cameraId, std::set<std::string>{});
+ }
+ if (newStatus != CameraDeviceStatus::PRESENT) {
+ mUnavailablePhysicalCameras[cameraId].insert(physicalCameraDeviceName);
+ } else {
+ mUnavailablePhysicalCameras[cameraId].erase(physicalCameraDeviceName);
+ }
+
*id = cameraId;
*physicalId = physicalCameraDeviceName.c_str();
return OK;
@@ -2282,20 +2278,6 @@
}
}
-void CameraProviderManager::ProviderInfo::notifyInitialStatusChange(
- sp<StatusListener> listener,
- std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus) {
- for (auto& statusInfo : *cachedStatus) {
- if (statusInfo.isPhysicalCameraStatus) {
- listener->onDeviceStatusChanged(String8(statusInfo.cameraId.c_str()),
- String8(statusInfo.physicalCameraId.c_str()), statusInfo.status);
- } else {
- listener->onDeviceStatusChanged(
- String8(statusInfo.cameraId.c_str()), statusInfo.status);
- }
- }
-}
-
CameraProviderManager::ProviderInfo::DeviceInfo3::DeviceInfo3(const std::string& name,
const metadata_vendor_id_t tagId, const std::string &id,
uint16_t minorVersion,
@@ -2645,9 +2627,6 @@
}
CameraProviderManager::ProviderInfo::~ProviderInfo() {
- if (mInitialStatusCallbackFuture.valid()) {
- mInitialStatusCallbackFuture.wait();
- }
// Destruction of ProviderInfo is only supposed to happen when the respective
// CameraProvider interface dies, so do not unregister callbacks.
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index d049aff..86047e8 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -23,7 +23,6 @@
#include <set>
#include <string>
#include <mutex>
-#include <future>
#include <camera/camera2/ConcurrentCamera.h>
#include <camera/CameraParameters2.h>
@@ -220,7 +219,14 @@
*/
std::pair<int, int> getCameraCount() const;
- std::vector<std::string> getCameraDeviceIds() const;
+ /**
+ * Upon the function return, if unavailablePhysicalIds is not nullptr, it
+ * will contain all of the unavailable physical camera Ids represented in
+ * the form of:
+ * {[logicalCamera, {physicalCamera1, physicalCamera2, ...}], ...}.
+ */
+ std::vector<std::string> getCameraDeviceIds(std::unordered_map<
+ std::string, std::set<std::string>>* unavailablePhysicalIds = nullptr) const;
/**
* Retrieve the number of API1 compatible cameras; these are internal and
@@ -607,6 +613,7 @@
};
std::vector<std::unique_ptr<DeviceInfo>> mDevices;
std::unordered_set<std::string> mUniqueCameraIds;
+ std::unordered_map<std::string, std::set<std::string>> mUnavailablePhysicalCameras;
int mUniqueDeviceCount;
std::vector<std::string> mUniqueAPI1CompatibleCameraIds;
// The initial public camera IDs published by the camera provider.
@@ -715,8 +722,6 @@
std::vector<CameraStatusInfoT> mCachedStatus;
// End of scope for mInitLock
- std::future<void> mInitialStatusCallbackFuture;
-
std::unique_ptr<ProviderInfo::DeviceInfo>
virtual initializeDeviceInfo(
const std::string &name, const metadata_vendor_id_t tagId,
@@ -724,9 +729,6 @@
virtual status_t reCacheConcurrentStreamingCameraIdsLocked() = 0;
- void notifyInitialStatusChange(sp<StatusListener> listener,
- std::unique_ptr<std::vector<CameraStatusInfoT>> cachedStatus);
-
std::vector<std::unordered_set<std::string>> mConcurrentCameraIdCombinations;
// Parse provider instance name for type and id
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index e9f6979..2f55def 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -102,23 +102,57 @@
sp<device::V3_2::ICameraDevice> mDeviceInterface;
hardware::hidl_vec<common::V1_0::VendorTagSection> mVendorTagSections;
+ // Whether to call a physical camera unavailable callback upon setCallback
+ bool mHasPhysicalCameraUnavailableCallback;
+ hardware::hidl_string mLogicalCameraId;
+ hardware::hidl_string mUnavailablePhysicalCameraId;
+
TestICameraProvider(const std::vector<hardware::hidl_string> &devices,
const hardware::hidl_vec<common::V1_0::VendorTagSection> &vendorSection) :
mDeviceNames(devices),
mDeviceInterface(new TestDeviceInterface(devices)),
- mVendorTagSections (vendorSection) {}
+ mVendorTagSections (vendorSection),
+ mHasPhysicalCameraUnavailableCallback(false) {}
TestICameraProvider(const std::vector<hardware::hidl_string> &devices,
const hardware::hidl_vec<common::V1_0::VendorTagSection> &vendorSection,
android::hardware::hidl_vec<uint8_t> chars) :
mDeviceNames(devices),
mDeviceInterface(new TestDeviceInterface(devices, chars)),
- mVendorTagSections (vendorSection) {}
+ mVendorTagSections (vendorSection),
+ mHasPhysicalCameraUnavailableCallback(false) {}
+
+ TestICameraProvider(const std::vector<hardware::hidl_string> &devices,
+ const hardware::hidl_vec<common::V1_0::VendorTagSection> &vendorSection,
+ android::hardware::hidl_vec<uint8_t> chars,
+ const hardware::hidl_string& logicalCameraId,
+ const hardware::hidl_string& unavailablePhysicalCameraId) :
+ mDeviceNames(devices),
+ mDeviceInterface(new TestDeviceInterface(devices, chars)),
+ mVendorTagSections (vendorSection),
+ mHasPhysicalCameraUnavailableCallback(true),
+ mLogicalCameraId(logicalCameraId),
+ mUnavailablePhysicalCameraId(unavailablePhysicalCameraId) {}
virtual hardware::Return<Status> setCallback(
const sp<provider::V2_4::ICameraProviderCallback>& callbacks) override {
mCalledCounter[SET_CALLBACK]++;
mCallbacks = callbacks;
+ if (mHasPhysicalCameraUnavailableCallback) {
+ auto cast26 = provider::V2_6::ICameraProviderCallback::castFrom(callbacks);
+ if (!cast26.isOk()) {
+ ADD_FAILURE() << "Failed to cast ICameraProviderCallback to V2_6";
+ } else {
+ sp<provider::V2_6::ICameraProviderCallback> callback26 = cast26;
+ if (callback26 == nullptr) {
+ ADD_FAILURE() << "V2_6::ICameraProviderCallback is null after conversion";
+ } else {
+ callback26->physicalCameraDeviceStatusChange(mLogicalCameraId,
+ mUnavailablePhysicalCameraId,
+ android::hardware::camera::common::V1_0::CameraDeviceStatus::NOT_PRESENT);
+ }
+ }
+ }
return hardware::Return<Status>(Status::OK);
}
@@ -266,12 +300,16 @@
};
struct TestStatusListener : public CameraProviderManager::StatusListener {
+ int mPhysicalCameraStatusChangeCount = 0;
+
~TestStatusListener() {}
void onDeviceStatusChanged(const String8 &,
CameraDeviceStatus) override {}
void onDeviceStatusChanged(const String8 &, const String8 &,
- CameraDeviceStatus) override {}
+ CameraDeviceStatus) override {
+ mPhysicalCameraStatusChangeCount++;
+ }
void onTorchStatusChanged(const String8 &,
TorchModeStatus) override {}
void onTorchStatusChanged(const String8 &,
@@ -634,3 +672,46 @@
ASSERT_EQ(deviceCount, deviceNames.size()) <<
"Unexpected amount of camera devices";
}
+
+// Test that CameraProviderManager does not trigger
+// onDeviceStatusChanged(NOT_PRESENT) for physical camera before initialize()
+// returns.
+TEST(CameraProviderManagerTest, PhysicalCameraAvailabilityCallbackRaceTest) {
+ std::vector<hardware::hidl_string> deviceNames;
+ deviceNames.push_back("device@3.2/test/0");
+ hardware::hidl_vec<common::V1_0::VendorTagSection> vendorSection;
+
+ sp<CameraProviderManager> providerManager = new CameraProviderManager();
+ sp<TestStatusListener> statusListener = new TestStatusListener();
+ TestInteractionProxy serviceProxy;
+
+ android::hardware::hidl_vec<uint8_t> chars;
+ CameraMetadata meta;
+ int32_t charKeys[] = { ANDROID_REQUEST_AVAILABLE_CAPABILITIES };
+ meta.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, charKeys,
+ sizeof(charKeys) / sizeof(charKeys[0]));
+ uint8_t capabilities[] = { ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA };
+ meta.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities,
+ sizeof(capabilities)/sizeof(capabilities[0]));
+ uint8_t physicalCameraIds[] = { '2', '\0', '3', '\0' };
+ meta.update(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS, physicalCameraIds,
+ sizeof(physicalCameraIds)/sizeof(physicalCameraIds[0]));
+ camera_metadata_t* metaBuffer = const_cast<camera_metadata_t*>(meta.getAndLock());
+ chars.setToExternal(reinterpret_cast<uint8_t*>(metaBuffer),
+ get_camera_metadata_size(metaBuffer));
+
+ sp<TestICameraProvider> provider = new TestICameraProvider(deviceNames,
+ vendorSection, chars, "device@3.2/test/0", "2");
+ serviceProxy.setProvider(provider);
+
+ status_t res = providerManager->initialize(statusListener, &serviceProxy);
+ ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
+
+ ASSERT_EQ(statusListener->mPhysicalCameraStatusChangeCount, 0)
+ << "Unexpected physical camera status change callback upon provider init.";
+
+ std::unordered_map<std::string, std::set<std::string>> unavailablePhysicalIds;
+ auto cameraIds = providerManager->getCameraDeviceIds(&unavailablePhysicalIds);
+ ASSERT_TRUE(unavailablePhysicalIds.count("0") > 0 && unavailablePhysicalIds["0"].count("2") > 0)
+ << "Unavailable physical camera Ids not set properly.";
+}