/*
 *  Copyright 2013 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.
 */

// Lifecycle notes: objects are owned where they will be called; in other words
// FooObservers are owned by C++-land, and user-callable objects (e.g.
// PeerConnection and VideoTrack) are owned by Java-land.
// When this file (or other files in this directory) allocates C++
// RefCountInterfaces it AddRef()s an artificial ref simulating the jlong held
// in Java-land, and then Release()s the ref in the respective free call.
// Sometimes this AddRef is implicit in the construction of a scoped_refptr<>
// which is then .release()d. Any persistent (non-local) references from C++ to
// Java must be global or weak (in which case they must be checked before use)!
//
// Exception notes: pretty much all JNI calls can throw Java exceptions, so each
// call through a JNIEnv* pointer needs to be followed by an ExceptionCheck()
// call. In this file this is done in CHECK_EXCEPTION, making for much easier
// debugging in case of failure (the alternative is to wait for control to
// return to the Java frame that called code in this file, at which point it's
// impossible to tell which JNI call broke).

#include "sdk/android/src/jni/pc/peerconnection.h"

#include <limits>
#include <memory>
#include <string>
#include <utility>

#include "absl/memory/memory.h"
#include "api/mediaconstraintsinterface.h"
#include "api/peerconnectioninterface.h"
#include "api/rtpreceiverinterface.h"
#include "api/rtpsenderinterface.h"
#include "api/rtptransceiverinterface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "sdk/android/generated_peerconnection_jni/jni/PeerConnection_jni.h"
#include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h"
#include "sdk/android/src/jni/pc/datachannel.h"
#include "sdk/android/src/jni/pc/icecandidate.h"
#include "sdk/android/src/jni/pc/mediaconstraints.h"
#include "sdk/android/src/jni/pc/mediastreamtrack.h"
#include "sdk/android/src/jni/pc/rtcstatscollectorcallbackwrapper.h"
#include "sdk/android/src/jni/pc/rtpsender.h"
#include "sdk/android/src/jni/pc/sdpobserver.h"
#include "sdk/android/src/jni/pc/sessiondescription.h"
#include "sdk/android/src/jni/pc/statsobserver.h"
#include "sdk/android/src/jni/pc/turncustomizer.h"

namespace webrtc {
namespace jni {

namespace {

PeerConnectionInterface* ExtractNativePC(JNIEnv* jni,
                                         const JavaRef<jobject>& j_pc) {
  return reinterpret_cast<OwnedPeerConnection*>(
             Java_PeerConnection_getNativeOwnedPeerConnection(jni, j_pc))
      ->pc();
}

PeerConnectionInterface::IceServers JavaToNativeIceServers(
    JNIEnv* jni,
    const JavaRef<jobject>& j_ice_servers) {
  PeerConnectionInterface::IceServers ice_servers;
  for (const JavaRef<jobject>& j_ice_server : Iterable(jni, j_ice_servers)) {
    ScopedJavaLocalRef<jobject> j_ice_server_tls_cert_policy =
        Java_IceServer_getTlsCertPolicy(jni, j_ice_server);
    ScopedJavaLocalRef<jobject> urls =
        Java_IceServer_getUrls(jni, j_ice_server);
    ScopedJavaLocalRef<jstring> username =
        Java_IceServer_getUsername(jni, j_ice_server);
    ScopedJavaLocalRef<jstring> password =
        Java_IceServer_getPassword(jni, j_ice_server);
    PeerConnectionInterface::TlsCertPolicy tls_cert_policy =
        JavaToNativeTlsCertPolicy(jni, j_ice_server_tls_cert_policy);
    ScopedJavaLocalRef<jstring> hostname =
        Java_IceServer_getHostname(jni, j_ice_server);
    ScopedJavaLocalRef<jobject> tls_alpn_protocols =
        Java_IceServer_getTlsAlpnProtocols(jni, j_ice_server);
    ScopedJavaLocalRef<jobject> tls_elliptic_curves =
        Java_IceServer_getTlsEllipticCurves(jni, j_ice_server);
    PeerConnectionInterface::IceServer server;
    server.urls = JavaListToNativeVector<std::string, jstring>(
        jni, urls, &JavaToNativeString);
    server.username = JavaToNativeString(jni, username);
    server.password = JavaToNativeString(jni, password);
    server.tls_cert_policy = tls_cert_policy;
    server.hostname = JavaToNativeString(jni, hostname);
    server.tls_alpn_protocols = JavaListToNativeVector<std::string, jstring>(
        jni, tls_alpn_protocols, &JavaToNativeString);
    server.tls_elliptic_curves = JavaListToNativeVector<std::string, jstring>(
        jni, tls_elliptic_curves, &JavaToNativeString);
    ice_servers.push_back(server);
  }
  return ice_servers;
}

SdpSemantics JavaToNativeSdpSemantics(JNIEnv* jni,
                                      const JavaRef<jobject>& j_sdp_semantics) {
  std::string enum_name = GetJavaEnumName(jni, j_sdp_semantics);

  if (enum_name == "PLAN_B")
    return SdpSemantics::kPlanB;

  if (enum_name == "UNIFIED_PLAN")
    return SdpSemantics::kUnifiedPlan;

  RTC_NOTREACHED();
  return SdpSemantics::kPlanB;
}

}  // namespace

void JavaToNativeRTCConfiguration(
    JNIEnv* jni,
    const JavaRef<jobject>& j_rtc_config,
    PeerConnectionInterface::RTCConfiguration* rtc_config) {
  ScopedJavaLocalRef<jobject> j_ice_transports_type =
      Java_RTCConfiguration_getIceTransportsType(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_bundle_policy =
      Java_RTCConfiguration_getBundlePolicy(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_rtcp_mux_policy =
      Java_RTCConfiguration_getRtcpMuxPolicy(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_tcp_candidate_policy =
      Java_RTCConfiguration_getTcpCandidatePolicy(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_candidate_network_policy =
      Java_RTCConfiguration_getCandidateNetworkPolicy(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_ice_servers =
      Java_RTCConfiguration_getIceServers(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_continual_gathering_policy =
      Java_RTCConfiguration_getContinualGatheringPolicy(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_turn_customizer =
      Java_RTCConfiguration_getTurnCustomizer(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_network_preference =
      Java_RTCConfiguration_getNetworkPreference(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_sdp_semantics =
      Java_RTCConfiguration_getSdpSemantics(jni, j_rtc_config);

  rtc_config->type = JavaToNativeIceTransportsType(jni, j_ice_transports_type);
  rtc_config->bundle_policy = JavaToNativeBundlePolicy(jni, j_bundle_policy);
  rtc_config->rtcp_mux_policy =
      JavaToNativeRtcpMuxPolicy(jni, j_rtcp_mux_policy);
  rtc_config->tcp_candidate_policy =
      JavaToNativeTcpCandidatePolicy(jni, j_tcp_candidate_policy);
  rtc_config->candidate_network_policy =
      JavaToNativeCandidateNetworkPolicy(jni, j_candidate_network_policy);
  rtc_config->servers = JavaToNativeIceServers(jni, j_ice_servers);
  rtc_config->audio_jitter_buffer_max_packets =
      Java_RTCConfiguration_getAudioJitterBufferMaxPackets(jni, j_rtc_config);
  rtc_config->audio_jitter_buffer_fast_accelerate =
      Java_RTCConfiguration_getAudioJitterBufferFastAccelerate(jni,
                                                               j_rtc_config);
  rtc_config->ice_connection_receiving_timeout =
      Java_RTCConfiguration_getIceConnectionReceivingTimeout(jni, j_rtc_config);
  rtc_config->ice_backup_candidate_pair_ping_interval =
      Java_RTCConfiguration_getIceBackupCandidatePairPingInterval(jni,
                                                                  j_rtc_config);
  rtc_config->continual_gathering_policy =
      JavaToNativeContinualGatheringPolicy(jni, j_continual_gathering_policy);
  rtc_config->ice_candidate_pool_size =
      Java_RTCConfiguration_getIceCandidatePoolSize(jni, j_rtc_config);
  rtc_config->prune_turn_ports =
      Java_RTCConfiguration_getPruneTurnPorts(jni, j_rtc_config);
  rtc_config->presume_writable_when_fully_relayed =
      Java_RTCConfiguration_getPresumeWritableWhenFullyRelayed(jni,
                                                               j_rtc_config);
  ScopedJavaLocalRef<jobject> j_ice_check_interval_strong_connectivity =
      Java_RTCConfiguration_getIceCheckIntervalStrongConnectivity(jni,
                                                                  j_rtc_config);
  rtc_config->ice_check_interval_strong_connectivity =
      JavaToNativeOptionalInt(jni, j_ice_check_interval_strong_connectivity);
  ScopedJavaLocalRef<jobject> j_ice_check_interval_weak_connectivity =
      Java_RTCConfiguration_getIceCheckIntervalWeakConnectivity(jni,
                                                                j_rtc_config);
  rtc_config->ice_check_interval_weak_connectivity =
      JavaToNativeOptionalInt(jni, j_ice_check_interval_weak_connectivity);
  ScopedJavaLocalRef<jobject> j_ice_check_min_interval =
      Java_RTCConfiguration_getIceCheckMinInterval(jni, j_rtc_config);
  rtc_config->ice_check_min_interval =
      JavaToNativeOptionalInt(jni, j_ice_check_min_interval);
  ScopedJavaLocalRef<jobject> j_ice_unwritable_timeout =
      Java_RTCConfiguration_getIceUnwritableTimeout(jni, j_rtc_config);
  rtc_config->ice_unwritable_timeout =
      JavaToNativeOptionalInt(jni, j_ice_unwritable_timeout);
  ScopedJavaLocalRef<jobject> j_ice_unwritable_min_checks =
      Java_RTCConfiguration_getIceUnwritableMinChecks(jni, j_rtc_config);
  rtc_config->ice_unwritable_min_checks =
      JavaToNativeOptionalInt(jni, j_ice_unwritable_min_checks);
  ScopedJavaLocalRef<jobject> j_stun_candidate_keepalive_interval =
      Java_RTCConfiguration_getStunCandidateKeepaliveInterval(jni,
                                                              j_rtc_config);
  rtc_config->stun_candidate_keepalive_interval =
      JavaToNativeOptionalInt(jni, j_stun_candidate_keepalive_interval);
  rtc_config->disable_ipv6_on_wifi =
      Java_RTCConfiguration_getDisableIPv6OnWifi(jni, j_rtc_config);
  rtc_config->max_ipv6_networks =
      Java_RTCConfiguration_getMaxIPv6Networks(jni, j_rtc_config);
  ScopedJavaLocalRef<jobject> j_ice_regather_interval_range =
      Java_RTCConfiguration_getIceRegatherIntervalRange(jni, j_rtc_config);
  if (!IsNull(jni, j_ice_regather_interval_range)) {
    int min = Java_IntervalRange_getMin(jni, j_ice_regather_interval_range);
    int max = Java_IntervalRange_getMax(jni, j_ice_regather_interval_range);
    rtc_config->ice_regather_interval_range.emplace(min, max);
  }

  rtc_config->turn_customizer = GetNativeTurnCustomizer(jni, j_turn_customizer);

  rtc_config->disable_ipv6 =
      Java_RTCConfiguration_getDisableIpv6(jni, j_rtc_config);
  rtc_config->media_config.enable_dscp =
      Java_RTCConfiguration_getEnableDscp(jni, j_rtc_config);
  rtc_config->media_config.video.enable_cpu_adaptation =
      Java_RTCConfiguration_getEnableCpuOveruseDetection(jni, j_rtc_config);
  rtc_config->enable_rtp_data_channel =
      Java_RTCConfiguration_getEnableRtpDataChannel(jni, j_rtc_config);
  rtc_config->media_config.video.suspend_below_min_bitrate =
      Java_RTCConfiguration_getSuspendBelowMinBitrate(jni, j_rtc_config);
  rtc_config->screencast_min_bitrate = JavaToNativeOptionalInt(
      jni, Java_RTCConfiguration_getScreencastMinBitrate(jni, j_rtc_config));
  rtc_config->combined_audio_video_bwe = JavaToNativeOptionalBool(
      jni, Java_RTCConfiguration_getCombinedAudioVideoBwe(jni, j_rtc_config));
  rtc_config->enable_dtls_srtp = JavaToNativeOptionalBool(
      jni, Java_RTCConfiguration_getEnableDtlsSrtp(jni, j_rtc_config));
  rtc_config->network_preference =
      JavaToNativeNetworkPreference(jni, j_network_preference);
  rtc_config->sdp_semantics = JavaToNativeSdpSemantics(jni, j_sdp_semantics);
  rtc_config->active_reset_srtp_params =
      Java_RTCConfiguration_getActiveResetSrtpParams(jni, j_rtc_config);
}

rtc::KeyType GetRtcConfigKeyType(JNIEnv* env,
                                 const JavaRef<jobject>& j_rtc_config) {
  return JavaToNativeKeyType(
      env, Java_RTCConfiguration_getKeyType(env, j_rtc_config));
}

PeerConnectionObserverJni::PeerConnectionObserverJni(
    JNIEnv* jni,
    const JavaRef<jobject>& j_observer)
    : j_observer_global_(jni, j_observer) {}

PeerConnectionObserverJni::~PeerConnectionObserverJni() = default;

void PeerConnectionObserverJni::OnIceCandidate(
    const IceCandidateInterface* candidate) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onIceCandidate(env, j_observer_global_,
                               NativeToJavaIceCandidate(env, *candidate));
}

void PeerConnectionObserverJni::OnIceCandidatesRemoved(
    const std::vector<cricket::Candidate>& candidates) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onIceCandidatesRemoved(
      env, j_observer_global_, NativeToJavaCandidateArray(env, candidates));
}

void PeerConnectionObserverJni::OnSignalingChange(
    PeerConnectionInterface::SignalingState new_state) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onSignalingChange(
      env, j_observer_global_,
      Java_SignalingState_fromNativeIndex(env, new_state));
}

void PeerConnectionObserverJni::OnIceConnectionChange(
    PeerConnectionInterface::IceConnectionState new_state) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onIceConnectionChange(
      env, j_observer_global_,
      Java_IceConnectionState_fromNativeIndex(env, new_state));
}

void PeerConnectionObserverJni::OnIceConnectionReceivingChange(bool receiving) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onIceConnectionReceivingChange(env, j_observer_global_,
                                               receiving);
}

void PeerConnectionObserverJni::OnIceGatheringChange(
    PeerConnectionInterface::IceGatheringState new_state) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onIceGatheringChange(
      env, j_observer_global_,
      Java_IceGatheringState_fromNativeIndex(env, new_state));
}

void PeerConnectionObserverJni::OnAddStream(
    rtc::scoped_refptr<MediaStreamInterface> stream) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onAddStream(
      env, j_observer_global_,
      GetOrCreateJavaStream(env, stream).j_media_stream());
}

void PeerConnectionObserverJni::OnRemoveStream(
    rtc::scoped_refptr<MediaStreamInterface> stream) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream);
  RTC_CHECK(it != remote_streams_.end()) << "unexpected stream: " << stream;
  Java_Observer_onRemoveStream(env, j_observer_global_,
                               it->second.j_media_stream());
  remote_streams_.erase(it);
}

void PeerConnectionObserverJni::OnDataChannel(
    rtc::scoped_refptr<DataChannelInterface> channel) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onDataChannel(env, j_observer_global_,
                              WrapNativeDataChannel(env, channel));
}

void PeerConnectionObserverJni::OnRenegotiationNeeded() {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  Java_Observer_onRenegotiationNeeded(env, j_observer_global_);
}

void PeerConnectionObserverJni::OnAddTrack(
    rtc::scoped_refptr<RtpReceiverInterface> receiver,
    const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  ScopedJavaLocalRef<jobject> j_rtp_receiver =
      NativeToJavaRtpReceiver(env, receiver);
  rtp_receivers_.emplace_back(env, j_rtp_receiver);

  Java_Observer_onAddTrack(env, j_observer_global_, j_rtp_receiver,
                           NativeToJavaMediaStreamArray(env, streams));
}

void PeerConnectionObserverJni::OnTrack(
    rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {
  JNIEnv* env = AttachCurrentThreadIfNeeded();
  ScopedJavaLocalRef<jobject> j_rtp_transceiver =
      NativeToJavaRtpTransceiver(env, transceiver);
  rtp_transceivers_.emplace_back(env, j_rtp_transceiver);

  Java_Observer_onTrack(env, j_observer_global_, j_rtp_transceiver);
}

// If the NativeToJavaStreamsMap contains the stream, return it.
// Otherwise, create a new Java MediaStream.
JavaMediaStream& PeerConnectionObserverJni::GetOrCreateJavaStream(
    JNIEnv* env,
    const rtc::scoped_refptr<MediaStreamInterface>& stream) {
  NativeToJavaStreamsMap::iterator it = remote_streams_.find(stream);
  if (it == remote_streams_.end()) {
    it = remote_streams_
             .emplace(std::piecewise_construct,
                      std::forward_as_tuple(stream.get()),
                      std::forward_as_tuple(env, stream))
             .first;
  }
  return it->second;
}

ScopedJavaLocalRef<jobjectArray>
PeerConnectionObserverJni::NativeToJavaMediaStreamArray(
    JNIEnv* jni,
    const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
  return NativeToJavaObjectArray(
      jni, streams, GetMediaStreamClass(jni),
      [this](JNIEnv* env, rtc::scoped_refptr<MediaStreamInterface> stream)
          -> const ScopedJavaGlobalRef<jobject>& {
        return GetOrCreateJavaStream(env, stream).j_media_stream();
      });
}

OwnedPeerConnection::OwnedPeerConnection(
    rtc::scoped_refptr<PeerConnectionInterface> peer_connection,
    std::unique_ptr<PeerConnectionObserver> observer,
    std::unique_ptr<MediaConstraintsInterface> constraints)
    : peer_connection_(peer_connection),
      observer_(std::move(observer)),
      constraints_(std::move(constraints)) {}

OwnedPeerConnection::~OwnedPeerConnection() {
  // Ensure that PeerConnection is destroyed before the observer.
  peer_connection_ = nullptr;
}

static jlong JNI_PeerConnection_CreatePeerConnectionObserver(
    JNIEnv* jni,
    const JavaParamRef<jclass>&,
    const JavaParamRef<jobject>& j_observer) {
  return jlongFromPointer(new PeerConnectionObserverJni(jni, j_observer));
}

static void JNI_PeerConnection_FreeOwnedPeerConnection(
    JNIEnv*,
    const JavaParamRef<jclass>&,
    jlong j_p) {
  delete reinterpret_cast<OwnedPeerConnection*>(j_p);
}

static jlong JNI_PeerConnection_GetNativePeerConnection(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  return jlongFromPointer(ExtractNativePC(jni, j_pc));
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetLocalDescription(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  const SessionDescriptionInterface* sdp =
      ExtractNativePC(jni, j_pc)->local_description();
  return sdp ? NativeToJavaSessionDescription(jni, sdp) : nullptr;
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetRemoteDescription(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  const SessionDescriptionInterface* sdp =
      ExtractNativePC(jni, j_pc)->remote_description();
  return sdp ? NativeToJavaSessionDescription(jni, sdp) : nullptr;
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_CreateDataChannel(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jstring>& j_label,
    const JavaParamRef<jobject>& j_init) {
  DataChannelInit init = JavaToNativeDataChannelInit(jni, j_init);
  rtc::scoped_refptr<DataChannelInterface> channel(
      ExtractNativePC(jni, j_pc)->CreateDataChannel(
          JavaToNativeString(jni, j_label), &init));
  return WrapNativeDataChannel(jni, channel);
}

static void JNI_PeerConnection_CreateOffer(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_observer,
    const JavaParamRef<jobject>& j_constraints) {
  std::unique_ptr<MediaConstraintsInterface> constraints =
      JavaToNativeMediaConstraints(jni, j_constraints);
  rtc::scoped_refptr<CreateSdpObserverJni> observer(
      new rtc::RefCountedObject<CreateSdpObserverJni>(jni, j_observer,
                                                      std::move(constraints)));
  ExtractNativePC(jni, j_pc)->CreateOffer(observer, observer->constraints());
}

static void JNI_PeerConnection_CreateAnswer(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_observer,
    const JavaParamRef<jobject>& j_constraints) {
  std::unique_ptr<MediaConstraintsInterface> constraints =
      JavaToNativeMediaConstraints(jni, j_constraints);
  rtc::scoped_refptr<CreateSdpObserverJni> observer(
      new rtc::RefCountedObject<CreateSdpObserverJni>(jni, j_observer,
                                                      std::move(constraints)));
  ExtractNativePC(jni, j_pc)->CreateAnswer(observer, observer->constraints());
}

static void JNI_PeerConnection_SetLocalDescription(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_observer,
    const JavaParamRef<jobject>& j_sdp) {
  rtc::scoped_refptr<SetSdpObserverJni> observer(
      new rtc::RefCountedObject<SetSdpObserverJni>(jni, j_observer, nullptr));
  ExtractNativePC(jni, j_pc)->SetLocalDescription(
      observer, JavaToNativeSessionDescription(jni, j_sdp).release());
}

static void JNI_PeerConnection_SetRemoteDescription(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_observer,
    const JavaParamRef<jobject>& j_sdp) {
  rtc::scoped_refptr<SetSdpObserverJni> observer(
      new rtc::RefCountedObject<SetSdpObserverJni>(jni, j_observer, nullptr));
  ExtractNativePC(jni, j_pc)->SetRemoteDescription(
      observer, JavaToNativeSessionDescription(jni, j_sdp).release());
}

static void JNI_PeerConnection_SetAudioPlayout(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    jboolean playout) {
  ExtractNativePC(jni, j_pc)->SetAudioPlayout(playout);
}

static void JNI_PeerConnection_SetAudioRecording(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    jboolean recording) {
  ExtractNativePC(jni, j_pc)->SetAudioRecording(recording);
}

static jboolean JNI_PeerConnection_SetConfiguration(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_rtc_config) {
  // Need to merge constraints into RTCConfiguration again, which are stored
  // in the OwnedPeerConnection object.
  OwnedPeerConnection* owned_pc = reinterpret_cast<OwnedPeerConnection*>(
      Java_PeerConnection_getNativeOwnedPeerConnection(jni, j_pc));
  PeerConnectionInterface::RTCConfiguration rtc_config(
      PeerConnectionInterface::RTCConfigurationType::kAggressive);
  JavaToNativeRTCConfiguration(jni, j_rtc_config, &rtc_config);
  if (owned_pc->constraints()) {
    CopyConstraintsIntoRtcConfiguration(owned_pc->constraints(), &rtc_config);
  }
  return owned_pc->pc()->SetConfiguration(rtc_config);
}

static jboolean JNI_PeerConnection_AddIceCandidate(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jstring>& j_sdp_mid,
    jint j_sdp_mline_index,
    const JavaParamRef<jstring>& j_candidate_sdp) {
  std::string sdp_mid = JavaToNativeString(jni, j_sdp_mid);
  std::string sdp = JavaToNativeString(jni, j_candidate_sdp);
  std::unique_ptr<IceCandidateInterface> candidate(
      CreateIceCandidate(sdp_mid, j_sdp_mline_index, sdp, nullptr));
  return ExtractNativePC(jni, j_pc)->AddIceCandidate(candidate.get());
}

static jboolean JNI_PeerConnection_RemoveIceCandidates(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobjectArray>& j_candidates) {
  std::vector<cricket::Candidate> candidates =
      JavaToNativeVector<cricket::Candidate>(jni, j_candidates,
                                             &JavaToNativeCandidate);
  return ExtractNativePC(jni, j_pc)->RemoveIceCandidates(candidates);
}

static jboolean JNI_PeerConnection_AddLocalStream(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    jlong native_stream) {
  return ExtractNativePC(jni, j_pc)->AddStream(
      reinterpret_cast<MediaStreamInterface*>(native_stream));
}

static void JNI_PeerConnection_RemoveLocalStream(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    jlong native_stream) {
  ExtractNativePC(jni, j_pc)->RemoveStream(
      reinterpret_cast<MediaStreamInterface*>(native_stream));
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_CreateSender(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jstring>& j_kind,
    const JavaParamRef<jstring>& j_stream_id) {
  std::string kind = JavaToNativeString(jni, j_kind);
  std::string stream_id = JavaToNativeString(jni, j_stream_id);
  rtc::scoped_refptr<RtpSenderInterface> sender =
      ExtractNativePC(jni, j_pc)->CreateSender(kind, stream_id);
  return NativeToJavaRtpSender(jni, sender);
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetSenders(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetSenders(),
                          &NativeToJavaRtpSender);
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetReceivers(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetReceivers(),
                          &NativeToJavaRtpReceiver);
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_GetTransceivers(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  return NativeToJavaList(jni, ExtractNativePC(jni, j_pc)->GetTransceivers(),
                          &NativeToJavaRtpTransceiver);
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_AddTrack(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const jlong native_track,
    const JavaParamRef<jobject>& j_stream_labels) {
  RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> result =
      ExtractNativePC(jni, j_pc)->AddTrack(
          reinterpret_cast<MediaStreamTrackInterface*>(native_track),
          JavaListToNativeVector<std::string, jstring>(jni, j_stream_labels,
                                                       &JavaToNativeString));
  if (!result.ok()) {
    RTC_LOG(LS_ERROR) << "Failed to add track: " << result.error().message();
    return nullptr;
  } else {
    return NativeToJavaRtpSender(jni, result.MoveValue());
  }
}

static jboolean JNI_PeerConnection_RemoveTrack(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    jlong native_sender) {
  return ExtractNativePC(jni, j_pc)->RemoveTrack(
      reinterpret_cast<RtpSenderInterface*>(native_sender));
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_AddTransceiverWithTrack(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    jlong native_track,
    const JavaParamRef<jobject>& j_init) {
  RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
      ExtractNativePC(jni, j_pc)->AddTransceiver(
          reinterpret_cast<MediaStreamTrackInterface*>(native_track),
          JavaToNativeRtpTransceiverInit(jni, j_init));
  if (!result.ok()) {
    RTC_LOG(LS_ERROR) << "Failed to add transceiver: "
                      << result.error().message();
    return nullptr;
  } else {
    return NativeToJavaRtpTransceiver(jni, result.MoveValue());
  }
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_AddTransceiverOfType(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_media_type,
    const JavaParamRef<jobject>& j_init) {
  RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>> result =
      ExtractNativePC(jni, j_pc)->AddTransceiver(
          JavaToNativeMediaType(jni, j_media_type),
          JavaToNativeRtpTransceiverInit(jni, j_init));
  if (!result.ok()) {
    RTC_LOG(LS_ERROR) << "Failed to add transceiver: "
                      << result.error().message();
    return nullptr;
  } else {
    return NativeToJavaRtpTransceiver(jni, result.MoveValue());
  }
}

static jboolean JNI_PeerConnection_OldGetStats(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_observer,
    jlong native_track) {
  rtc::scoped_refptr<StatsObserverJni> observer(
      new rtc::RefCountedObject<StatsObserverJni>(jni, j_observer));
  return ExtractNativePC(jni, j_pc)->GetStats(
      observer, reinterpret_cast<MediaStreamTrackInterface*>(native_track),
      PeerConnectionInterface::kStatsOutputLevelStandard);
}

static void JNI_PeerConnection_NewGetStats(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_callback) {
  rtc::scoped_refptr<RTCStatsCollectorCallbackWrapper> callback(
      new rtc::RefCountedObject<RTCStatsCollectorCallbackWrapper>(jni,
                                                                  j_callback));
  ExtractNativePC(jni, j_pc)->GetStats(callback);
}

static jboolean JNI_PeerConnection_SetBitrate(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    const JavaParamRef<jobject>& j_min,
    const JavaParamRef<jobject>& j_current,
    const JavaParamRef<jobject>& j_max) {
  PeerConnectionInterface::BitrateParameters params;
  params.min_bitrate_bps = JavaToNativeOptionalInt(jni, j_min);
  params.current_bitrate_bps = JavaToNativeOptionalInt(jni, j_current);
  params.max_bitrate_bps = JavaToNativeOptionalInt(jni, j_max);
  return ExtractNativePC(jni, j_pc)->SetBitrate(params).ok();
}

static jboolean JNI_PeerConnection_StartRtcEventLog(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc,
    int file_descriptor,
    int max_size_bytes) {
  return ExtractNativePC(jni, j_pc)->StartRtcEventLog(file_descriptor,
                                                      max_size_bytes);
}

static void JNI_PeerConnection_StopRtcEventLog(
    JNIEnv* jni,
    const JavaParamRef<jobject>& j_pc) {
  ExtractNativePC(jni, j_pc)->StopRtcEventLog();
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_SignalingState(
    JNIEnv* env,
    const JavaParamRef<jobject>& j_pc) {
  return Java_SignalingState_fromNativeIndex(
      env, ExtractNativePC(env, j_pc)->signaling_state());
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_IceConnectionState(
    JNIEnv* env,
    const JavaParamRef<jobject>& j_pc) {
  return Java_IceConnectionState_fromNativeIndex(
      env, ExtractNativePC(env, j_pc)->ice_connection_state());
}

static ScopedJavaLocalRef<jobject> JNI_PeerConnection_IceGatheringState(
    JNIEnv* env,
    const JavaParamRef<jobject>& j_pc) {
  return Java_IceGatheringState_fromNativeIndex(
      env, ExtractNativePC(env, j_pc)->ice_gathering_state());
}

static void JNI_PeerConnection_Close(JNIEnv* jni,
                                     const JavaParamRef<jobject>& j_pc) {
  ExtractNativePC(jni, j_pc)->Close();
}

}  // namespace jni
}  // namespace webrtc
