Expose peer connection's `getStats` by RtpSender/Receiver in Android SDK Currently if you want to obtain the stats for a specific sender/receiver in Android, you need to call peerConnection.getStats() and filter manually the result by sender. pc.getStats(receiver/sender) exists in c++ and ios but was not exposed in Android Bug: webrtc:14547 Change-Id: I9954434880f0f93821fcd2e2de24a875e8d136ae Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/275880 Reviewed-by: Xavier Lepaul‎ <xalep@webrtc.org> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38428}
diff --git a/AUTHORS b/AUTHORS index 2fdd9fd..a0632d2 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -141,6 +141,7 @@ Facebook Inc. <*@fb.com> Google Inc. <*@google.com> Highfive, Inc. <*@highfive.com> +Hopin Ltd. <*@hopin.to> HyperConnect Inc. <*@hpcnt.com> Intel Corporation <*@intel.com> LG Electronics, Inc. <*@lge.com>
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java index 724f704..2d592a5 100644 --- a/sdk/android/api/org/webrtc/PeerConnection.java +++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -1177,6 +1177,22 @@ } /** + * Gets stats using the new stats collection API, see webrtc/api/stats/. These + * will replace old stats collection API when the new API has matured enough. + */ + public void getStats(RtpSender sender, RTCStatsCollectorCallback callback) { + nativeNewGetStatsSender(sender.getNativeRtpSender(), callback); + } + + /** + * Gets stats using the new stats collection API, see webrtc/api/stats/. These + * will replace old stats collection API when the new API has matured enough. + */ + public void getStats(RtpReceiver receiver, RTCStatsCollectorCallback callback) { + nativeNewGetStatsReceiver(receiver.getNativeRtpReceiver(), callback); + } + + /** * Limits the bandwidth allocated for all RTP streams sent by this * PeerConnection. Pass null to leave a value unchanged. */ @@ -1310,6 +1326,8 @@ private native void nativeRemoveLocalStream(long stream); private native boolean nativeOldGetStats(StatsObserver observer, long nativeTrack); private native void nativeNewGetStats(RTCStatsCollectorCallback callback); + private native void nativeNewGetStatsSender(long sender, RTCStatsCollectorCallback callback); + private native void nativeNewGetStatsReceiver(long receiver, RTCStatsCollectorCallback callback); private native RtpSender nativeCreateSender(String kind, String stream_id); private native List<RtpSender> nativeGetSenders(); private native List<RtpReceiver> nativeGetReceivers();
diff --git a/sdk/android/api/org/webrtc/RtpReceiver.java b/sdk/android/api/org/webrtc/RtpReceiver.java index a5710f9..c3cff3d 100644 --- a/sdk/android/api/org/webrtc/RtpReceiver.java +++ b/sdk/android/api/org/webrtc/RtpReceiver.java
@@ -49,6 +49,12 @@ return nativeGetId(nativeRtpReceiver); } + /** Returns a pointer to webrtc::RtpReceiverInterface. */ + long getNativeRtpReceiver() { + checkRtpReceiverExists(); + return nativeRtpReceiver; + } + @CalledByNative public void dispose() { checkRtpReceiverExists();
diff --git a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java index f71bd36..d763ff2 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/PeerConnectionEndToEndTest.java
@@ -931,6 +931,23 @@ assertTrue(offeringPC.setBitrate(100000, 5000000, 500000000)); assertFalse(offeringPC.setBitrate(3, 2, 1)); + // Test getStats by Sender interface + offeringExpectations.expectNewStatsCallback(); + offeringPC.getStats(videoSender, offeringExpectations); + assertTrue(offeringExpectations.waitForAllExpectationsToBeSatisfied(DEFAULT_TIMEOUT_SECONDS)); + + // Test getStats by Receiver interface + RtpReceiver videoReceiver = null; + for (RtpReceiver receiver : answeringPC.getReceivers()) { + if (receiver.track().kind().equals("video")) { + videoReceiver = receiver; + } + } + assertNotNull(videoReceiver); + answeringExpectations.expectNewStatsCallback(); + answeringPC.getStats(videoReceiver, answeringExpectations); + assertTrue(answeringExpectations.waitForAllExpectationsToBeSatisfied(DEFAULT_TIMEOUT_SECONDS)); + // Free the Java-land objects and collect them. shutdownPC(offeringPC, offeringExpectations); offeringPC = null;
diff --git a/sdk/android/src/jni/pc/peer_connection.cc b/sdk/android/src/jni/pc/peer_connection.cc index 03321a5..8c76b42 100644 --- a/sdk/android/src/jni/pc/peer_connection.cc +++ b/sdk/android/src/jni/pc/peer_connection.cc
@@ -842,6 +842,32 @@ ExtractNativePC(jni, j_pc)->GetStats(callback.get()); } +static void JNI_PeerConnection_NewGetStatsSender( + JNIEnv* jni, + const JavaParamRef<jobject>& j_pc, + jlong native_sender, + const JavaParamRef<jobject>& j_callback) { + auto callback = + rtc::make_ref_counted<RTCStatsCollectorCallbackWrapper>(jni, j_callback); + ExtractNativePC(jni, j_pc)->GetStats( + rtc::scoped_refptr<RtpSenderInterface>( + reinterpret_cast<RtpSenderInterface*>(native_sender)), + rtc::scoped_refptr<RTCStatsCollectorCallbackWrapper>(callback.get())); +} + +static void JNI_PeerConnection_NewGetStatsReceiver( + JNIEnv* jni, + const JavaParamRef<jobject>& j_pc, + jlong native_receiver, + const JavaParamRef<jobject>& j_callback) { + auto callback = + rtc::make_ref_counted<RTCStatsCollectorCallbackWrapper>(jni, j_callback); + ExtractNativePC(jni, j_pc)->GetStats( + rtc::scoped_refptr<RtpReceiverInterface>( + reinterpret_cast<RtpReceiverInterface*>(native_receiver)), + rtc::scoped_refptr<RTCStatsCollectorCallbackWrapper>(callback.get())); +} + static jboolean JNI_PeerConnection_SetBitrate( JNIEnv* jni, const JavaParamRef<jobject>& j_pc,