Adding PeerConnection.Observer.onTrack to the Java SDK.

Bug: webrtc:8869
Change-Id: I4c33f9ddf293af8c093a8726431a3574ff2b6e39
Reviewed-on: https://webrtc-review.googlesource.com/73966
Commit-Queue: Seth Hampson <shampson@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23155}
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index dfe4b61..71a258e 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -109,6 +109,13 @@
      * setRemoteDescription.
      */
     @CalledByNative("Observer") void onAddTrack(RtpReceiver receiver, MediaStream[] mediaStreams);
+
+    /**
+     * Triggered when the signaling from SetRemoteDescription indicates that a transceiver
+     * will be receiving media from a remote endpoint. This is only called if UNIFIED_PLAN
+     * semantics are specified. The transceiver will be disposed automatically.
+     */
+    @CalledByNative("Observer") default void onTrack(RtpTransceiver transceiver){};
   }
 
   /** Java version of PeerConnectionInterface.IceServer. */
diff --git a/sdk/android/api/org/webrtc/RtpTransceiver.java b/sdk/android/api/org/webrtc/RtpTransceiver.java
index d77ecb4..3086950 100644
--- a/sdk/android/api/org/webrtc/RtpTransceiver.java
+++ b/sdk/android/api/org/webrtc/RtpTransceiver.java
@@ -196,6 +196,7 @@
     nativeStop(nativeRtpTransceiver);
   }
 
+  @CalledByNative
   public void dispose() {
     cachedSender.dispose();
     cachedReceiver.dispose();
diff --git a/sdk/android/src/jni/pc/peerconnection.cc b/sdk/android/src/jni/pc/peerconnection.cc
index 16e40d1..225443f 100644
--- a/sdk/android/src/jni/pc/peerconnection.cc
+++ b/sdk/android/src/jni/pc/peerconnection.cc
@@ -49,7 +49,6 @@
 #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/rtptransceiver.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"
@@ -335,6 +334,16 @@
                            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(
diff --git a/sdk/android/src/jni/pc/peerconnection.h b/sdk/android/src/jni/pc/peerconnection.h
index 6b021a0..669d360 100644
--- a/sdk/android/src/jni/pc/peerconnection.h
+++ b/sdk/android/src/jni/pc/peerconnection.h
@@ -21,6 +21,7 @@
 #include "sdk/android/src/jni/pc/mediaconstraints.h"
 #include "sdk/android/src/jni/pc/mediastream.h"
 #include "sdk/android/src/jni/pc/rtpreceiver.h"
+#include "sdk/android/src/jni/pc/rtptransceiver.h"
 
 namespace webrtc {
 namespace jni {
@@ -60,6 +61,8 @@
   void OnAddTrack(rtc::scoped_refptr<RtpReceiverInterface> receiver,
                   const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
                       streams) override;
+  void OnTrack(
+      rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override;
 
  private:
   typedef std::map<MediaStreamInterface*, JavaMediaStream>
@@ -83,6 +86,10 @@
   // C++ -> Java remote streams.
   NativeToJavaStreamsMap remote_streams_;
   std::vector<JavaRtpReceiverGlobalOwner> rtp_receivers_;
+  // Holds a reference to the Java transceivers given to the AddTrack
+  // callback, so that the shared ownership by the Java object will be
+  // properly disposed.
+  std::vector<JavaRtpTransceiverGlobalOwner> rtp_transceivers_;
 };
 
 // PeerConnection doesn't take ownership of the observer. In Java API, we don't
diff --git a/sdk/android/src/jni/pc/rtptransceiver.cc b/sdk/android/src/jni/pc/rtptransceiver.cc
index f142d58..0a115c2 100644
--- a/sdk/android/src/jni/pc/rtptransceiver.cc
+++ b/sdk/android/src/jni/pc/rtptransceiver.cc
@@ -62,6 +62,20 @@
       env, jlongFromPointer(transceiver.release()));
 }
 
+JavaRtpTransceiverGlobalOwner::JavaRtpTransceiverGlobalOwner(
+    JNIEnv* env,
+    const JavaRef<jobject>& j_transceiver)
+    : j_transceiver_(env, j_transceiver){};
+
+JavaRtpTransceiverGlobalOwner::JavaRtpTransceiverGlobalOwner(
+    JavaRtpTransceiverGlobalOwner&& other) = default;
+
+JavaRtpTransceiverGlobalOwner::~JavaRtpTransceiverGlobalOwner() {
+  if (j_transceiver_.obj()) {
+    Java_RtpTransceiver_dispose(AttachCurrentThreadIfNeeded(), j_transceiver_);
+  }
+}
+
 ScopedJavaLocalRef<jobject> JNI_RtpTransceiver_GetMediaType(
     JNIEnv* jni,
     const base::android::JavaParamRef<jclass>&,
diff --git a/sdk/android/src/jni/pc/rtptransceiver.h b/sdk/android/src/jni/pc/rtptransceiver.h
index 9017c2f..61f3e0c 100644
--- a/sdk/android/src/jni/pc/rtptransceiver.h
+++ b/sdk/android/src/jni/pc/rtptransceiver.h
@@ -27,6 +27,19 @@
     JNIEnv* env,
     rtc::scoped_refptr<RtpTransceiverInterface> transceiver);
 
+// This takes ownership of the of the |j_transceiver| and stores it as a global
+// reference. This calls the Java Transceiver's dispose() method with the dtor.
+class JavaRtpTransceiverGlobalOwner {
+ public:
+  JavaRtpTransceiverGlobalOwner(JNIEnv* env,
+                                const JavaRef<jobject>& j_transceiver);
+  JavaRtpTransceiverGlobalOwner(JavaRtpTransceiverGlobalOwner&& other);
+  ~JavaRtpTransceiverGlobalOwner();
+
+ private:
+  ScopedJavaGlobalRef<jobject> j_transceiver_;
+};
+
 }  // namespace jni
 }  // namespace webrtc