Android: Allow injecting native PeerConnection.

This allows application to construct PeerConnection object in JNI and
pass that to Android API. API for wrapping Java PeerConnection Observers
is exposed for convenience.

Bug: webrtc:8662
Change-Id: Id110b92e6bb5ab00661cd50616d05c3e18a1697d
Reviewed-on: https://webrtc-review.googlesource.com/34520
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21379}
diff --git a/sdk/android/api/org/webrtc/NativePeerConnectionFactory.java b/sdk/android/api/org/webrtc/NativePeerConnectionFactory.java
new file mode 100644
index 0000000..63ecf10
--- /dev/null
+++ b/sdk/android/api/org/webrtc/NativePeerConnectionFactory.java
@@ -0,0 +1,20 @@
+/*
+ *  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.
+ */
+
+package org.webrtc;
+
+/** Factory for creating webrtc::PeerConnectionInterface instances. */
+public interface NativePeerConnectionFactory {
+  /**
+   * Create a new webrtc::PeerConnectionInterface instance and returns a pointer to it.
+   * The caller takes ownership of the object.
+   */
+  long createNativePeerConnection();
+}
diff --git a/sdk/android/api/org/webrtc/PeerConnection.java b/sdk/android/api/org/webrtc/PeerConnection.java
index 6c27872..8eddfa8 100644
--- a/sdk/android/api/org/webrtc/PeerConnection.java
+++ b/sdk/android/api/org/webrtc/PeerConnection.java
@@ -551,6 +551,14 @@
   private List<RtpSender> senders = new ArrayList<>();
   private List<RtpReceiver> receivers = new ArrayList<>();
 
+  /**
+   * Wraps a PeerConnection created by the factory. Can be used by clients that want to implement
+   * their PeerConnection creation in JNI.
+   */
+  public PeerConnection(NativePeerConnectionFactory factory) {
+    this(factory.createNativePeerConnection(), 0 /* nativeObserver */);
+  }
+
   PeerConnection(long nativePeerConnection, long nativeObserver) {
     this.nativePeerConnection = nativePeerConnection;
     this.nativeObserver = nativeObserver;
@@ -745,7 +753,9 @@
     }
     receivers.clear();
     JniCommon.nativeReleaseRef(nativePeerConnection);
-    freeObserver(nativeObserver);
+    if (nativeObserver != 0) {
+      freeNativePeerConnectionObserver(nativeObserver);
+    }
   }
 
   @CalledByNative
@@ -753,7 +763,8 @@
     return nativePeerConnection;
   }
 
-  private static native void freeObserver(long nativeObserver);
+  public static native long createNativePeerConnectionObserver(Observer observer);
+  public static native void freeNativePeerConnectionObserver(long nativeObserver);
 
   private native boolean setNativeConfiguration(RTCConfiguration config, long nativeObserver);
 
diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
index c51ebd2..c8c5b9a 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -226,7 +226,7 @@
   @Deprecated
   public PeerConnection createPeerConnection(PeerConnection.RTCConfiguration rtcConfig,
       MediaConstraints constraints, PeerConnection.Observer observer) {
-    long nativeObserver = createNativeObserver(observer);
+    long nativeObserver = PeerConnection.createNativePeerConnectionObserver(observer);
     if (nativeObserver == 0) {
       return null;
     }
@@ -388,8 +388,6 @@
       VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory,
       long nativeAudioProcessor);
 
-  private static native long createNativeObserver(PeerConnection.Observer observer);
-
   private static native long createNativePeerConnection(long nativeFactory,
       PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver);