Add Java binding for new getStats implementation.

Very similar to the current interface, but matches the new C++ structure, and
exposes the stats values as Objects which can be downcast to more specific
types (where the previous API only exposed the values as strings).

BUG=webrtc:6871

Review-Url: https://codereview.webrtc.org/2807933003
Cr-Commit-Position: refs/heads/master@{#17746}
This commit is contained in:
deadbeef
2017-04-18 10:27:51 -07:00
committed by Commit bot
parent 0fafb1ac8f
commit 82215872f8
10 changed files with 582 additions and 13 deletions

View File

@ -45,8 +45,15 @@ void FreeGlobalClassReferenceHolder() {
ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
LoadClass(jni, "android/graphics/SurfaceTexture");
LoadClass(jni, "java/lang/Boolean");
LoadClass(jni, "java/lang/Double");
LoadClass(jni, "java/lang/Integer");
LoadClass(jni, "java/lang/Long");
LoadClass(jni, "java/lang/String");
LoadClass(jni, "java/math/BigInteger");
LoadClass(jni, "java/nio/ByteBuffer");
LoadClass(jni, "java/util/ArrayList");
LoadClass(jni, "java/util/LinkedHashMap");
LoadClass(jni, "org/webrtc/AudioTrack");
LoadClass(jni, "org/webrtc/Camera1Enumerator");
LoadClass(jni, "org/webrtc/Camera2Enumerator");
@ -86,6 +93,8 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) {
LoadClass(jni, "org/webrtc/PeerConnection$CandidateNetworkPolicy");
LoadClass(jni, "org/webrtc/PeerConnection$KeyType");
LoadClass(jni, "org/webrtc/PeerConnection$SignalingState");
LoadClass(jni, "org/webrtc/RTCStats");
LoadClass(jni, "org/webrtc/RTCStatsReport");
LoadClass(jni, "org/webrtc/RtpReceiver");
LoadClass(jni, "org/webrtc/RtpSender");
LoadClass(jni, "org/webrtc/SessionDescription");

View File

@ -73,6 +73,7 @@
#include "webrtc/sdk/android/src/jni/classreferenceholder.h"
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
#include "webrtc/sdk/android/src/jni/native_handle_impl.h"
#include "webrtc/sdk/android/src/jni/rtcstatscollectorcallbackwrapper.h"
#include "webrtc/system_wrappers/include/field_trial_default.h"
#include "webrtc/system_wrappers/include/logcat_trace_context.h"
#include "webrtc/system_wrappers/include/trace.h"
@ -2123,8 +2124,8 @@ JOW(jobject, PeerConnection_nativeGetReceivers)(JNIEnv* jni, jobject j_pc) {
return j_receivers;
}
JOW(bool, PeerConnection_nativeGetStats)(
JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
JOW(bool, PeerConnection_nativeOldGetStats)
(JNIEnv* jni, jobject j_pc, jobject j_observer, jlong native_track) {
rtc::scoped_refptr<StatsObserverWrapper> observer(
new rtc::RefCountedObject<StatsObserverWrapper>(jni, j_observer));
return ExtractNativePC(jni, j_pc)->GetStats(
@ -2133,6 +2134,14 @@ JOW(bool, PeerConnection_nativeGetStats)(
PeerConnectionInterface::kStatsOutputLevelStandard);
}
JOW(void, PeerConnection_nativeNewGetStats)
(JNIEnv* jni, jobject j_pc, jobject j_callback) {
rtc::scoped_refptr<RTCStatsCollectorCallbackWrapper> callback(
new rtc::RefCountedObject<RTCStatsCollectorCallbackWrapper>(jni,
j_callback));
ExtractNativePC(jni, j_pc)->GetStats(callback);
}
JOW(bool, PeerConnection_nativeStartRtcEventLog)(
JNIEnv* jni, jobject j_pc, int file_descriptor, int max_size_bytes) {
return ExtractNativePC(jni, j_pc)->StartRtcEventLog(file_descriptor,

View File

@ -0,0 +1,267 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/sdk/android/src/jni/rtcstatscollectorcallbackwrapper.h"
#include <string>
#include <vector>
#include "webrtc/sdk/android/src/jni/classreferenceholder.h"
namespace webrtc_jni {
RTCStatsCollectorCallbackWrapper::RTCStatsCollectorCallbackWrapper(
JNIEnv* jni,
jobject j_callback)
: j_callback_global_(jni, j_callback),
j_callback_class_(jni, GetObjectClass(jni, j_callback)),
j_stats_report_class_(FindClass(jni, "org/webrtc/RTCStatsReport")),
j_stats_report_ctor_(GetMethodID(jni,
j_stats_report_class_,
"<init>",
"(JLjava/util/Map;)V")),
j_stats_class_(FindClass(jni, "org/webrtc/RTCStats")),
j_stats_ctor_(GetMethodID(
jni,
j_stats_class_,
"<init>",
"(JLjava/lang/String;Ljava/lang/String;Ljava/util/Map;)V")),
j_linked_hash_map_class_(FindClass(jni, "java/util/LinkedHashMap")),
j_linked_hash_map_ctor_(
GetMethodID(jni, j_linked_hash_map_class_, "<init>", "()V")),
j_linked_hash_map_put_(GetMethodID(
jni,
j_linked_hash_map_class_,
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")),
j_boolean_class_(FindClass(jni, "java/lang/Boolean")),
j_boolean_ctor_(GetMethodID(jni, j_boolean_class_, "<init>", "(Z)V")),
j_integer_class_(FindClass(jni, "java/lang/Integer")),
j_integer_ctor_(GetMethodID(jni, j_integer_class_, "<init>", "(I)V")),
j_long_class_(FindClass(jni, "java/lang/Long")),
j_long_ctor_(GetMethodID(jni, j_long_class_, "<init>", "(J)V")),
j_big_integer_class_(FindClass(jni, "java/math/BigInteger")),
j_big_integer_ctor_(GetMethodID(jni,
j_big_integer_class_,
"<init>",
"(Ljava/lang/String;)V")),
j_double_class_(FindClass(jni, "java/lang/Double")),
j_double_ctor_(GetMethodID(jni, j_double_class_, "<init>", "(D)V")),
j_string_class_(FindClass(jni, "java/lang/String")) {}
void RTCStatsCollectorCallbackWrapper::OnStatsDelivered(
const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) {
JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedLocalRefFrame local_ref_frame(jni);
jobject j_report = ReportToJava(jni, report);
jmethodID m = GetMethodID(jni, *j_callback_class_, "onStatsDelivered",
"(Lorg/webrtc/RTCStatsReport;)V");
jni->CallVoidMethod(*j_callback_global_, m, j_report);
CHECK_EXCEPTION(jni) << "error during CallVoidMethod";
}
jobject RTCStatsCollectorCallbackWrapper::ReportToJava(
JNIEnv* jni,
const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) {
jobject j_stats_map =
jni->NewObject(j_linked_hash_map_class_, j_linked_hash_map_ctor_);
CHECK_EXCEPTION(jni) << "error during NewObject";
for (const webrtc::RTCStats& stats : *report) {
// Create a local reference frame for each RTCStats, since there is a
// maximum number of references that can be created in one frame.
ScopedLocalRefFrame local_ref_frame(jni);
jstring j_id = JavaStringFromStdString(jni, stats.id());
jobject j_stats = StatsToJava(jni, stats);
jni->CallObjectMethod(j_stats_map, j_linked_hash_map_put_, j_id, j_stats);
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
}
jobject j_report = jni->NewObject(j_stats_report_class_, j_stats_report_ctor_,
report->timestamp_us(), j_stats_map);
CHECK_EXCEPTION(jni) << "error during NewObject";
return j_report;
}
jobject RTCStatsCollectorCallbackWrapper::StatsToJava(
JNIEnv* jni,
const webrtc::RTCStats& stats) {
jstring j_type = JavaStringFromStdString(jni, stats.type());
jstring j_id = JavaStringFromStdString(jni, stats.id());
jobject j_members =
jni->NewObject(j_linked_hash_map_class_, j_linked_hash_map_ctor_);
for (const webrtc::RTCStatsMemberInterface* member : stats.Members()) {
if (!member->is_defined()) {
continue;
}
// Create a local reference frame for each member as well.
ScopedLocalRefFrame local_ref_frame(jni);
jstring j_name = JavaStringFromStdString(jni, member->name());
jobject j_member = MemberToJava(jni, member);
jni->CallObjectMethod(j_members, j_linked_hash_map_put_, j_name, j_member);
CHECK_EXCEPTION(jni) << "error during CallObjectMethod";
}
jobject j_stats =
jni->NewObject(j_stats_class_, j_stats_ctor_, stats.timestamp_us(),
j_type, j_id, j_members);
CHECK_EXCEPTION(jni) << "error during NewObject";
return j_stats;
}
jobject RTCStatsCollectorCallbackWrapper::MemberToJava(
JNIEnv* jni,
const webrtc::RTCStatsMemberInterface* member) {
switch (member->type()) {
case webrtc::RTCStatsMemberInterface::kBool: {
jobject value =
jni->NewObject(j_boolean_class_, j_boolean_ctor_,
*member->cast_to<webrtc::RTCStatsMember<bool>>());
CHECK_EXCEPTION(jni) << "error during NewObject";
return value;
}
case webrtc::RTCStatsMemberInterface::kInt32: {
jobject value =
jni->NewObject(j_integer_class_, j_integer_ctor_,
*member->cast_to<webrtc::RTCStatsMember<int32_t>>());
CHECK_EXCEPTION(jni) << "error during NewObject";
return value;
}
case webrtc::RTCStatsMemberInterface::kUint32: {
jobject value = jni->NewObject(
j_long_class_, j_long_ctor_,
(jlong)*member->cast_to<webrtc::RTCStatsMember<uint32_t>>());
CHECK_EXCEPTION(jni) << "error during NewObject";
return value;
}
case webrtc::RTCStatsMemberInterface::kInt64: {
jobject value =
jni->NewObject(j_long_class_, j_long_ctor_,
*member->cast_to<webrtc::RTCStatsMember<int64_t>>());
CHECK_EXCEPTION(jni) << "error during NewObject";
return value;
}
case webrtc::RTCStatsMemberInterface::kUint64: {
jobject value =
jni->NewObject(j_big_integer_class_, j_big_integer_ctor_,
JavaStringFromStdString(jni, member->ValueToString()));
CHECK_EXCEPTION(jni) << "error during NewObject";
return value;
}
case webrtc::RTCStatsMemberInterface::kDouble: {
jobject value =
jni->NewObject(j_double_class_, j_double_ctor_,
*member->cast_to<webrtc::RTCStatsMember<double>>());
CHECK_EXCEPTION(jni) << "error during NewObject";
return value;
}
case webrtc::RTCStatsMemberInterface::kString: {
return JavaStringFromStdString(
jni, *member->cast_to<webrtc::RTCStatsMember<std::string>>());
}
case webrtc::RTCStatsMemberInterface::kSequenceBool: {
const std::vector<bool>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<bool>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_boolean_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jobject value =
jni->NewObject(j_boolean_class_, j_boolean_ctor_, values[i]);
jni->SetObjectArrayElement(j_values, i, value);
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
case webrtc::RTCStatsMemberInterface::kSequenceInt32: {
const std::vector<int32_t>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<int32_t>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_integer_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jobject value =
jni->NewObject(j_integer_class_, j_integer_ctor_, values[i]);
jni->SetObjectArrayElement(j_values, i, value);
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
case webrtc::RTCStatsMemberInterface::kSequenceUint32: {
const std::vector<uint32_t>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<uint32_t>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_long_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jobject value = jni->NewObject(j_long_class_, j_long_ctor_, values[i]);
jni->SetObjectArrayElement(j_values, i, value);
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
case webrtc::RTCStatsMemberInterface::kSequenceInt64: {
const std::vector<int64_t>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<int64_t>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_long_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jobject value = jni->NewObject(j_long_class_, j_long_ctor_, values[i]);
jni->SetObjectArrayElement(j_values, i, value);
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
case webrtc::RTCStatsMemberInterface::kSequenceUint64: {
const std::vector<uint64_t>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<uint64_t>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_big_integer_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jobject value = jni->NewObject(
j_big_integer_class_, j_big_integer_ctor_,
JavaStringFromStdString(jni, rtc::ToString(values[i])));
jni->SetObjectArrayElement(j_values, i, value);
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
case webrtc::RTCStatsMemberInterface::kSequenceDouble: {
const std::vector<double>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<double>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_double_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jobject value =
jni->NewObject(j_double_class_, j_double_ctor_, values[i]);
jni->SetObjectArrayElement(j_values, i, value);
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
case webrtc::RTCStatsMemberInterface::kSequenceString: {
const std::vector<std::string>& values =
*member->cast_to<webrtc::RTCStatsMember<std::vector<std::string>>>();
jobjectArray j_values =
jni->NewObjectArray(values.size(), j_string_class_, nullptr);
CHECK_EXCEPTION(jni) << "error during NewObjectArray";
for (size_t i = 0; i < values.size(); ++i) {
jni->SetObjectArrayElement(j_values, i,
JavaStringFromStdString(jni, values[i]));
CHECK_EXCEPTION(jni) << "error during SetObjectArrayElement";
}
return j_values;
}
}
RTC_NOTREACHED();
return nullptr;
}
} // namespace webrtc_jni

View File

@ -0,0 +1,65 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_SDK_ANDROID_SRC_JNI_RTCSTATSCOLLECTORCALLBACKWRAPPER_H_
#define WEBRTC_SDK_ANDROID_SRC_JNI_RTCSTATSCOLLECTORCALLBACKWRAPPER_H_
#include <jni.h>
#include "webrtc/api/peerconnectioninterface.h"
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
namespace webrtc_jni {
// Adapter for a Java RTCStatsCollectorCallback presenting a C++
// RTCStatsCollectorCallback and dispatching the callback from C++ back to
// Java.
class RTCStatsCollectorCallbackWrapper
: public webrtc::RTCStatsCollectorCallback {
public:
RTCStatsCollectorCallbackWrapper(JNIEnv* jni, jobject j_callback);
void OnStatsDelivered(
const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report) override;
private:
// Helper functions for converting C++ RTCStatsReport to Java equivalent.
jobject ReportToJava(
JNIEnv* jni,
const rtc::scoped_refptr<const webrtc::RTCStatsReport>& report);
jobject StatsToJava(JNIEnv* jni, const webrtc::RTCStats& stats);
jobject MemberToJava(JNIEnv* jni,
const webrtc::RTCStatsMemberInterface* member);
const ScopedGlobalRef<jobject> j_callback_global_;
const ScopedGlobalRef<jclass> j_callback_class_;
const jclass j_stats_report_class_;
const jmethodID j_stats_report_ctor_;
const jclass j_stats_class_;
const jmethodID j_stats_ctor_;
const jclass j_linked_hash_map_class_;
const jmethodID j_linked_hash_map_ctor_;
const jmethodID j_linked_hash_map_put_;
const jclass j_boolean_class_;
const jmethodID j_boolean_ctor_;
const jclass j_integer_class_;
const jmethodID j_integer_ctor_;
const jclass j_long_class_;
const jmethodID j_long_ctor_;
const jclass j_big_integer_class_;
const jmethodID j_big_integer_ctor_;
const jclass j_double_class_;
const jmethodID j_double_ctor_;
const jclass j_string_class_;
};
} // namespace webrtc_jni
#endif // WEBRTC_SDK_ANDROID_SRC_JNI_RTCSTATSCOLLECTORCALLBACKWRAPPER_H_