Allow passing in a custom native library loader.
All previous initialize methods are deprecated and a new initialize that uses a builder pattern is added. This gives us full control over the order of initialization. Bug: webrtc:7474 Change-Id: I006190e50f2e75c5015f0be75b86d367676db2cc Reviewed-on: https://webrtc-review.googlesource.com/4160 Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20037}
This commit is contained in:
committed by
Commit Bot
parent
7bcfc3b232
commit
5cd1cfb7c4
@ -378,14 +378,6 @@ public class PeerConnectionClient {
|
||||
}
|
||||
|
||||
private void createPeerConnectionFactoryInternal(Context context) {
|
||||
PeerConnectionFactory.initializeInternalTracer();
|
||||
if (peerConnectionParameters.tracing) {
|
||||
PeerConnectionFactory.startInternalTracingCapture(
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
|
||||
+ "webrtc-trace.txt");
|
||||
}
|
||||
Log.d(TAG,
|
||||
"Create peer connection factory. Use video: " + peerConnectionParameters.videoCallEnabled);
|
||||
isError = false;
|
||||
|
||||
// Initialize field trials.
|
||||
@ -424,8 +416,21 @@ public class PeerConnectionClient {
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "Preferred video codec: " + preferredVideoCodec);
|
||||
PeerConnectionFactory.initializeFieldTrials(fieldTrials);
|
||||
Log.d(TAG, "Field trials: " + fieldTrials);
|
||||
|
||||
// Initialize WebRTC
|
||||
Log.d(TAG,
|
||||
"Initialize WebRTC. Field trials: " + fieldTrials + " Enable video HW acceleration: "
|
||||
+ peerConnectionParameters.videoCodecHwAcceleration);
|
||||
PeerConnectionFactory.initialize(
|
||||
PeerConnectionFactory.InitializationOptions.builder(context)
|
||||
.setFieldTrials(fieldTrials)
|
||||
.setEnableVideoHwAcceleration(peerConnectionParameters.videoCodecHwAcceleration)
|
||||
.createInitializationOptions());
|
||||
if (peerConnectionParameters.tracing) {
|
||||
PeerConnectionFactory.startInternalTracingCapture(
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
|
||||
+ "webrtc-trace.txt");
|
||||
}
|
||||
|
||||
// Check if ISAC is used by default.
|
||||
preferIsac = peerConnectionParameters.audioCodec != null
|
||||
@ -504,8 +509,6 @@ public class PeerConnectionClient {
|
||||
});
|
||||
|
||||
// Create peer connection factory.
|
||||
PeerConnectionFactory.initializeAndroidGlobals(
|
||||
context, peerConnectionParameters.videoCodecHwAcceleration);
|
||||
if (options != null) {
|
||||
Log.d(TAG, "Factory networkIgnoreMask option: " + options.networkIgnoreMask);
|
||||
}
|
||||
|
||||
@ -23,17 +23,13 @@ public class ContextUtils {
|
||||
|
||||
/**
|
||||
* Stores the application context that will be returned by getApplicationContext. This is called
|
||||
* by PeerConnectionFactory.initializeAndroidGlobals.
|
||||
* by PeerConnectionFactory.initialize. The application context must be set before creating
|
||||
* a PeerConnectionFactory and must not be modified while it is alive.
|
||||
*/
|
||||
public static void initialize(Context applicationContext) {
|
||||
if (ContextUtils.applicationContext != null) {
|
||||
// TODO(sakal): Re-enable after the migration period.
|
||||
// throw new RuntimeException("Multiple ContextUtils.initialize calls.");
|
||||
Logging.e(
|
||||
TAG, "Calling ContextUtils.initialize multiple times, this will crash in the future!");
|
||||
}
|
||||
if (applicationContext == null) {
|
||||
throw new RuntimeException("Application context cannot be null for ContextUtils.initialize.");
|
||||
throw new IllegalArgumentException(
|
||||
"Application context cannot be null for ContextUtils.initialize.");
|
||||
}
|
||||
ContextUtils.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@ -30,8 +30,6 @@ public class Logging {
|
||||
private static final Logger fallbackLogger = createFallbackLogger();
|
||||
private static volatile boolean tracingEnabled;
|
||||
private static volatile boolean loggingEnabled;
|
||||
private static enum NativeLibStatus { UNINITIALIZED, LOADED, FAILED }
|
||||
private static volatile NativeLibStatus nativeLibStatus = NativeLibStatus.UNINITIALIZED;
|
||||
|
||||
private static Logger createFallbackLogger() {
|
||||
final Logger fallbackLogger = Logger.getLogger("org.webrtc.Logging");
|
||||
@ -39,19 +37,6 @@ public class Logging {
|
||||
return fallbackLogger;
|
||||
}
|
||||
|
||||
private static boolean loadNativeLibrary() {
|
||||
if (nativeLibStatus == NativeLibStatus.UNINITIALIZED) {
|
||||
try {
|
||||
System.loadLibrary("jingle_peerconnection_so");
|
||||
nativeLibStatus = NativeLibStatus.LOADED;
|
||||
} catch (UnsatisfiedLinkError t) {
|
||||
nativeLibStatus = NativeLibStatus.FAILED;
|
||||
fallbackLogger.log(Level.WARNING, "Failed to load jingle_peerconnection_so: ", t);
|
||||
}
|
||||
}
|
||||
return nativeLibStatus == NativeLibStatus.LOADED;
|
||||
}
|
||||
|
||||
// Keep in sync with webrtc/common_types.h:TraceLevel.
|
||||
public enum TraceLevel {
|
||||
TRACE_NONE(0x0000),
|
||||
@ -80,19 +65,10 @@ public class Logging {
|
||||
public enum Severity { LS_SENSITIVE, LS_VERBOSE, LS_INFO, LS_WARNING, LS_ERROR, LS_NONE }
|
||||
|
||||
public static void enableLogThreads() {
|
||||
if (!loadNativeLibrary()) {
|
||||
fallbackLogger.log(Level.WARNING, "Cannot enable log thread because native lib not loaded.");
|
||||
return;
|
||||
}
|
||||
nativeEnableLogThreads();
|
||||
}
|
||||
|
||||
public static void enableLogTimeStamps() {
|
||||
if (!loadNativeLibrary()) {
|
||||
fallbackLogger.log(
|
||||
Level.WARNING, "Cannot enable log timestamps because native lib not loaded.");
|
||||
return;
|
||||
}
|
||||
nativeEnableLogTimeStamps();
|
||||
}
|
||||
|
||||
@ -100,11 +76,6 @@ public class Logging {
|
||||
// On Android, use "logcat:" for |path| to send output there.
|
||||
// Note: this function controls the output of the WEBRTC_TRACE() macros.
|
||||
public static synchronized void enableTracing(String path, EnumSet<TraceLevel> levels) {
|
||||
if (!loadNativeLibrary()) {
|
||||
fallbackLogger.log(Level.WARNING, "Cannot enable tracing because native lib not loaded.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tracingEnabled) {
|
||||
return;
|
||||
}
|
||||
@ -120,10 +91,6 @@ public class Logging {
|
||||
// output. On Android, the output will be directed to Logcat.
|
||||
// Note: this function starts collecting the output of the LOG() macros.
|
||||
public static synchronized void enableLogToDebugOutput(Severity severity) {
|
||||
if (!loadNativeLibrary()) {
|
||||
fallbackLogger.log(Level.WARNING, "Cannot enable logging because native lib not loaded.");
|
||||
return;
|
||||
}
|
||||
nativeEnableLogToDebugOutput(severity.ordinal());
|
||||
loggingEnabled = true;
|
||||
}
|
||||
|
||||
@ -401,6 +401,7 @@ android_library("libjingle_peerconnection_java") {
|
||||
"api/org/webrtc/MediaSource.java",
|
||||
"api/org/webrtc/MediaStream.java",
|
||||
"api/org/webrtc/MediaStreamTrack.java",
|
||||
"api/org/webrtc/NativeLibraryLoader.java",
|
||||
"api/org/webrtc/NetworkMonitor.java",
|
||||
"api/org/webrtc/NetworkMonitorAutoDetect.java",
|
||||
"api/org/webrtc/PeerConnection.java",
|
||||
@ -451,6 +452,7 @@ android_library("libjingle_peerconnection_java") {
|
||||
"src/java/org/webrtc/I420BufferImpl.java",
|
||||
"src/java/org/webrtc/JniCommon.java",
|
||||
"src/java/org/webrtc/MediaCodecUtils.java",
|
||||
"src/java/org/webrtc/NativeLibrary.java",
|
||||
"src/java/org/webrtc/NV12Buffer.java",
|
||||
"src/java/org/webrtc/NV21Buffer.java",
|
||||
"src/java/org/webrtc/TextureBufferImpl.java",
|
||||
|
||||
24
sdk/android/api/org/webrtc/NativeLibraryLoader.java
Normal file
24
sdk/android/api/org/webrtc/NativeLibraryLoader.java
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 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;
|
||||
|
||||
/**
|
||||
* Interface for loading native libraries. A custom loader can be passed to
|
||||
* PeerConnectionFactory.initialize.
|
||||
*/
|
||||
public interface NativeLibraryLoader {
|
||||
/**
|
||||
* Loads a native library with the given name.
|
||||
*
|
||||
* @return True on success
|
||||
*/
|
||||
boolean load(String name);
|
||||
}
|
||||
@ -18,15 +18,10 @@ import java.util.List;
|
||||
* the PeerConnection API for clients.
|
||||
*/
|
||||
public class PeerConnectionFactory {
|
||||
private static volatile boolean nativeLibLoaded;
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("jingle_peerconnection_so");
|
||||
nativeLibLoaded = true;
|
||||
} catch (UnsatisfiedLinkError t) {
|
||||
nativeLibLoaded = false;
|
||||
}
|
||||
// TODO(sakal): Remove once all dependencies have started using
|
||||
// PeerConnectionFactory.initialize.
|
||||
NativeLibrary.initialize(new NativeLibrary.DefaultLoader());
|
||||
}
|
||||
|
||||
public static final String TRIAL_ENABLED = "Enabled";
|
||||
@ -42,6 +37,65 @@ public class PeerConnectionFactory {
|
||||
private EglBase localEglbase;
|
||||
private EglBase remoteEglbase;
|
||||
|
||||
public static class InitializationOptions {
|
||||
final Context applicationContext;
|
||||
final String fieldTrials;
|
||||
final boolean enableInternalTracer;
|
||||
final boolean enableVideoHwAcceleration;
|
||||
final NativeLibraryLoader nativeLibraryLoader;
|
||||
|
||||
private InitializationOptions(Context applicationContext, String fieldTrials,
|
||||
boolean enableInternalTracer, boolean enableVideoHwAcceleration,
|
||||
NativeLibraryLoader nativeLibraryLoader) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.fieldTrials = fieldTrials;
|
||||
this.enableInternalTracer = enableInternalTracer;
|
||||
this.enableVideoHwAcceleration = enableVideoHwAcceleration;
|
||||
this.nativeLibraryLoader = nativeLibraryLoader;
|
||||
}
|
||||
|
||||
public static Builder builder(Context applicationContext) {
|
||||
return new Builder(applicationContext);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final Context applicationContext;
|
||||
private String fieldTrials = "";
|
||||
private boolean enableInternalTracer = true;
|
||||
private boolean enableVideoHwAcceleration = true;
|
||||
private NativeLibraryLoader nativeLibraryLoader = new NativeLibrary.DefaultLoader();
|
||||
|
||||
Builder(Context applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public Builder setFieldTrials(String fieldTrials) {
|
||||
this.fieldTrials = fieldTrials;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEnableInternalTracer(boolean enableInternalTracer) {
|
||||
this.enableInternalTracer = enableInternalTracer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEnableVideoHwAcceleration(boolean enableVideoHwAcceleration) {
|
||||
this.enableVideoHwAcceleration = enableVideoHwAcceleration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setNativeLibraryLoader(NativeLibraryLoader nativeLibraryLoader) {
|
||||
this.nativeLibraryLoader = nativeLibraryLoader;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PeerConnectionFactory.InitializationOptions createInitializationOptions() {
|
||||
return new PeerConnectionFactory.InitializationOptions(applicationContext, fieldTrials,
|
||||
enableInternalTracer, enableVideoHwAcceleration, nativeLibraryLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Options {
|
||||
// Keep in sync with webrtc/rtc_base/network.h!
|
||||
static final int ADAPTER_TYPE_UNKNOWN = 0;
|
||||
@ -56,17 +110,35 @@ public class PeerConnectionFactory {
|
||||
public boolean disableNetworkMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and initializes WebRTC. This must be called at least once before creating a
|
||||
* PeerConnectionFactory. Replaces all the old initialization methods. Must not be called while
|
||||
* a PeerConnectionFactory is alive.
|
||||
*/
|
||||
public static void initialize(InitializationOptions options) {
|
||||
ContextUtils.initialize(options.applicationContext);
|
||||
NativeLibrary.initialize(options.nativeLibraryLoader);
|
||||
nativeInitializeAndroidGlobals(options.applicationContext, options.enableVideoHwAcceleration);
|
||||
initializeFieldTrials(options.fieldTrials);
|
||||
if (options.enableInternalTracer) {
|
||||
initializeInternalTracer();
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called at least once before creating a PeerConnectionFactory
|
||||
// (for example, at application startup time).
|
||||
public static native void nativeInitializeAndroidGlobals(
|
||||
private static native void nativeInitializeAndroidGlobals(
|
||||
Context context, boolean videoHwAcceleration);
|
||||
|
||||
// Deprecated, use PeerConnectionFactory.initialize instead.
|
||||
@Deprecated
|
||||
public static void initializeAndroidGlobals(Context context, boolean videoHwAcceleration) {
|
||||
ContextUtils.initialize(context);
|
||||
nativeInitializeAndroidGlobals(context, videoHwAcceleration);
|
||||
}
|
||||
|
||||
// Older signature of initializeAndroidGlobals. The extra parameters are now meaningless.
|
||||
// Deprecated, use PeerConnectionFactory.initialize instead.
|
||||
@Deprecated
|
||||
public static boolean initializeAndroidGlobals(Object context, boolean initializeAudio,
|
||||
boolean initializeVideo, boolean videoHwAcceleration) {
|
||||
@ -76,7 +148,8 @@ public class PeerConnectionFactory {
|
||||
|
||||
// Field trial initialization. Must be called before PeerConnectionFactory
|
||||
// is created.
|
||||
public static native void initializeFieldTrials(String fieldTrialsInitString);
|
||||
// Deprecated, use PeerConnectionFactory.initialize instead.
|
||||
@Deprecated public static native void initializeFieldTrials(String fieldTrialsInitString);
|
||||
// Wrapper of webrtc::field_trial::FindFullName. Develop the feature with default behaviour off.
|
||||
// Example usage:
|
||||
// if (PeerConnectionFactory.fieldTrialsFindFullName("WebRTCExperiment").equals("Enabled")) {
|
||||
@ -85,12 +158,13 @@ public class PeerConnectionFactory {
|
||||
// method2();
|
||||
// }
|
||||
public static String fieldTrialsFindFullName(String name) {
|
||||
return nativeLibLoaded ? nativeFieldTrialsFindFullName(name) : "";
|
||||
return NativeLibrary.isLoaded() ? nativeFieldTrialsFindFullName(name) : "";
|
||||
}
|
||||
private static native String nativeFieldTrialsFindFullName(String name);
|
||||
// Internal tracing initialization. Must be called before PeerConnectionFactory is created to
|
||||
// prevent racing with tracing code.
|
||||
public static native void initializeInternalTracer();
|
||||
// Deprecated, use PeerConnectionFactory.initialize instead.
|
||||
@Deprecated public static native void initializeInternalTracer();
|
||||
// Internal tracing shutdown, called to prevent resource leaks. Must be called after
|
||||
// PeerConnectionFactory is gone to prevent races with code performing tracing.
|
||||
public static native void shutdownInternalTracer();
|
||||
@ -111,6 +185,11 @@ public class PeerConnectionFactory {
|
||||
|
||||
public PeerConnectionFactory(
|
||||
Options options, VideoEncoderFactory encoderFactory, VideoDecoderFactory decoderFactory) {
|
||||
if (!NativeLibrary.isLoaded() || ContextUtils.getApplicationContext() == null) {
|
||||
throw new IllegalStateException(
|
||||
"PeerConnectionFactory.initialize was not called before creating a "
|
||||
+ "PeerConnectionFactory.");
|
||||
}
|
||||
nativeFactory = nativeCreatePeerConnectionFactory(options, encoderFactory, decoderFactory);
|
||||
if (nativeFactory == 0) {
|
||||
throw new RuntimeException("Failed to initialize PeerConnectionFactory!");
|
||||
|
||||
54
sdk/android/src/java/org/webrtc/NativeLibrary.java
Normal file
54
sdk/android/src/java/org/webrtc/NativeLibrary.java
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 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;
|
||||
|
||||
class NativeLibrary {
|
||||
private static String TAG = "NativeLibrary";
|
||||
|
||||
static class DefaultLoader implements NativeLibraryLoader {
|
||||
@Override
|
||||
public boolean load(String name) {
|
||||
Logging.d(TAG, "Loading library: " + name);
|
||||
try {
|
||||
System.loadLibrary(name);
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
Logging.e(TAG, "Failed to load native library: " + name, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object lock = new Object();
|
||||
private static boolean libraryLoaded = false;
|
||||
|
||||
/**
|
||||
* Loads the native library. Clients should call PeerConnectionFactory.initialize. It will call
|
||||
* this method for them.
|
||||
*/
|
||||
static void initialize(NativeLibraryLoader loader) {
|
||||
synchronized (lock) {
|
||||
if (libraryLoaded) {
|
||||
Logging.d(TAG, "Native library has already been loaded.");
|
||||
return;
|
||||
}
|
||||
Logging.d(TAG, "Loading native library.");
|
||||
libraryLoaded = loader.load("jingle_peerconnection_so");
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the library has been loaded successfully. */
|
||||
static boolean isLoaded() {
|
||||
synchronized (lock) {
|
||||
return libraryLoaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user