summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/utility
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/modules/utility
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/modules/utility')
-rw-r--r--third_party/libwebrtc/modules/utility/BUILD.gn78
-rw-r--r--third_party/libwebrtc/modules/utility/DEPS5
-rw-r--r--third_party/libwebrtc/modules/utility/OWNERS1
-rw-r--r--third_party/libwebrtc/modules/utility/include/helpers_android.h80
-rw-r--r--third_party/libwebrtc/modules/utility/include/jvm_android.h193
-rw-r--r--third_party/libwebrtc/modules/utility/maybe_worker_thread.cc99
-rw-r--r--third_party/libwebrtc/modules/utility/maybe_worker_thread.h86
-rw-r--r--third_party/libwebrtc/modules/utility/maybe_worker_thread_unittests.cc161
-rw-r--r--third_party/libwebrtc/modules/utility/source/helpers_android.cc117
-rw-r--r--third_party/libwebrtc/modules/utility/source/jvm_android.cc292
-rw-r--r--third_party/libwebrtc/modules/utility/utility_gn/moz.build229
11 files changed, 1341 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/utility/BUILD.gn b/third_party/libwebrtc/modules/utility/BUILD.gn
new file mode 100644
index 0000000000..46bca17f02
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/BUILD.gn
@@ -0,0 +1,78 @@
+# Copyright (c) 2014 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.
+
+import("../../webrtc.gni")
+
+rtc_source_set("utility") {
+ sources = [
+ "maybe_worker_thread.cc",
+ "maybe_worker_thread.h",
+ ]
+
+ deps = [
+ "../../api:field_trials_view",
+ "../../api:sequence_checker",
+ "../../api/task_queue",
+ "../../api/task_queue:pending_task_safety_flag",
+ "../../rtc_base:checks",
+ "../../rtc_base:logging",
+ "../../rtc_base:macromagic",
+ "../../rtc_base:rtc_event",
+ "../../rtc_base:rtc_task_queue",
+ ]
+
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/functional:any_invocable",
+ "//third_party/abseil-cpp/absl/strings:strings",
+ ]
+
+ if (is_android) {
+ visibility = [ "*" ]
+ sources += [
+ "include/helpers_android.h",
+ "include/jvm_android.h",
+ "source/helpers_android.cc",
+ "source/jvm_android.cc",
+ ]
+
+ deps += [
+ "../../api:sequence_checker",
+ "../../rtc_base:checks",
+ "../../rtc_base:logging",
+ "../../rtc_base:platform_thread",
+ "../../rtc_base/system:arch",
+ ]
+
+ if (build_with_mozilla) {
+ sources -= [ "source/jvm_android.cc" ]
+ }
+ }
+}
+
+if (rtc_include_tests) {
+ rtc_library("utility_unittests") {
+ testonly = true
+
+ sources = [ "maybe_worker_thread_unittests.cc" ]
+ deps = [
+ ":utility",
+ "../../api:sequence_checker",
+ "../../api/task_queue",
+ "../../api/task_queue:default_task_queue_factory",
+ "../../api/task_queue:pending_task_safety_flag",
+ "../../api/units:time_delta",
+ "../../rtc_base:rtc_event",
+ "../../rtc_base:threading",
+ "../../test:explicit_key_value_config",
+ "../../test:field_trial",
+ "../../test:test_main",
+ "../../test:test_support",
+ "../../test/time_controller",
+ ]
+ }
+}
diff --git a/third_party/libwebrtc/modules/utility/DEPS b/third_party/libwebrtc/modules/utility/DEPS
new file mode 100644
index 0000000000..e9017d6b27
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+ "+common_audio",
+ "+common_video",
+ "+system_wrappers",
+]
diff --git a/third_party/libwebrtc/modules/utility/OWNERS b/third_party/libwebrtc/modules/utility/OWNERS
new file mode 100644
index 0000000000..5904b95df7
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/OWNERS
@@ -0,0 +1 @@
+perkj@webrtc.org
diff --git a/third_party/libwebrtc/modules/utility/include/helpers_android.h b/third_party/libwebrtc/modules/utility/include/helpers_android.h
new file mode 100644
index 0000000000..5e8deb9536
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/include/helpers_android.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#ifndef MODULES_UTILITY_INCLUDE_HELPERS_ANDROID_H_
+#define MODULES_UTILITY_INCLUDE_HELPERS_ANDROID_H_
+
+#include <jni.h>
+
+#include <string>
+
+#include "rtc_base/system/arch.h"
+
+// Abort the process if `jni` has a Java exception pending.
+// TODO(henrika): merge with CHECK_JNI_EXCEPTION() in jni_helpers.h.
+#define CHECK_EXCEPTION(jni) \
+ RTC_CHECK(!jni->ExceptionCheck()) \
+ << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
+
+#if defined(WEBRTC_ARCH_X86)
+// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on
+// x86 - use force_align_arg_pointer to realign the stack at the JNI
+// boundary. bugs.webrtc.org/9050
+#define JNI_FUNCTION_ALIGN __attribute__((force_align_arg_pointer))
+#else
+#define JNI_FUNCTION_ALIGN
+#endif
+
+namespace webrtc {
+
+// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
+JNIEnv* GetEnv(JavaVM* jvm);
+
+// Return a `jlong` that will correctly convert back to `ptr`. This is needed
+// because the alternative (of silently passing a 32-bit pointer to a vararg
+// function expecting a 64-bit param) picks up garbage in the high 32 bits.
+jlong PointerTojlong(void* ptr);
+
+// JNIEnv-helper methods that wraps the API which uses the JNI interface
+// pointer (JNIEnv*). It allows us to RTC_CHECK success and that no Java
+// exception is thrown while calling the method.
+jmethodID GetMethodID(JNIEnv* jni,
+ jclass c,
+ const char* name,
+ const char* signature);
+
+jmethodID GetStaticMethodID(JNIEnv* jni,
+ jclass c,
+ const char* name,
+ const char* signature);
+
+jclass FindClass(JNIEnv* jni, const char* name);
+
+jobject NewGlobalRef(JNIEnv* jni, jobject o);
+
+void DeleteGlobalRef(JNIEnv* jni, jobject o);
+
+// Attach thread to JVM if necessary and detach at scope end if originally
+// attached.
+class AttachThreadScoped {
+ public:
+ explicit AttachThreadScoped(JavaVM* jvm);
+ ~AttachThreadScoped();
+ JNIEnv* env();
+
+ private:
+ bool attached_;
+ JavaVM* jvm_;
+ JNIEnv* env_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_UTILITY_INCLUDE_HELPERS_ANDROID_H_
diff --git a/third_party/libwebrtc/modules/utility/include/jvm_android.h b/third_party/libwebrtc/modules/utility/include/jvm_android.h
new file mode 100644
index 0000000000..bafb8f2c15
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/include/jvm_android.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2015 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 MODULES_UTILITY_INCLUDE_JVM_ANDROID_H_
+#define MODULES_UTILITY_INCLUDE_JVM_ANDROID_H_
+
+#include <jni.h>
+
+#include <memory>
+#include <string>
+
+#include "api/sequence_checker.h"
+#include "modules/utility/include/helpers_android.h"
+
+namespace webrtc {
+
+// RAII JavaVM AttachCurrentThread/DetachCurrentThread object.
+//
+// The JNI interface pointer (JNIEnv) is valid only in the current thread.
+// Should another thread need to access the Java VM, it must first call
+// AttachCurrentThread() to attach itself to the VM and obtain a JNI interface
+// pointer. The native thread remains attached to the VM until it calls
+// DetachCurrentThread() to detach.
+class JvmThreadConnector {
+ public:
+ JvmThreadConnector();
+ ~JvmThreadConnector();
+
+ private:
+ SequenceChecker thread_checker_;
+ bool attached_;
+};
+
+// This class is created by the NativeRegistration class and is used to wrap
+// the actual Java object handle (jobject) on which we can call methods from
+// C++ in to Java. See example in JVM for more details.
+// TODO(henrika): extend support for type of function calls.
+class GlobalRef {
+ public:
+ GlobalRef(JNIEnv* jni, jobject object);
+ ~GlobalRef();
+
+ jboolean CallBooleanMethod(jmethodID methodID, ...);
+ jint CallIntMethod(jmethodID methodID, ...);
+ void CallVoidMethod(jmethodID methodID, ...);
+
+ private:
+ JNIEnv* const jni_;
+ const jobject j_object_;
+};
+
+// Wraps the jclass object on which we can call GetMethodId() functions to
+// query method IDs.
+class JavaClass {
+ public:
+ JavaClass(JNIEnv* jni, jclass clazz) : jni_(jni), j_class_(clazz) {}
+ ~JavaClass() {}
+
+ jmethodID GetMethodId(const char* name, const char* signature);
+ jmethodID GetStaticMethodId(const char* name, const char* signature);
+ jobject CallStaticObjectMethod(jmethodID methodID, ...);
+ jint CallStaticIntMethod(jmethodID methodID, ...);
+
+ protected:
+ JNIEnv* const jni_;
+ jclass const j_class_;
+};
+
+// Adds support of the NewObject factory method to the JavaClass class.
+// See example in JVM for more details on how to use it.
+class NativeRegistration : public JavaClass {
+ public:
+ NativeRegistration(JNIEnv* jni, jclass clazz);
+ ~NativeRegistration();
+
+ std::unique_ptr<GlobalRef> NewObject(const char* name,
+ const char* signature,
+ ...);
+
+ private:
+ JNIEnv* const jni_;
+};
+
+// This class is created by the JVM class and is used to expose methods that
+// needs the JNI interface pointer but its main purpose is to create a
+// NativeRegistration object given name of a Java class and a list of native
+// methods. See example in JVM for more details.
+class JNIEnvironment {
+ public:
+ explicit JNIEnvironment(JNIEnv* jni);
+ ~JNIEnvironment();
+
+ // Registers native methods with the Java class specified by `name`.
+ // Note that the class name must be one of the names in the static
+ // `loaded_classes` array defined in jvm_android.cc.
+ // This method must be called on the construction thread.
+ std::unique_ptr<NativeRegistration> RegisterNatives(
+ const char* name,
+ const JNINativeMethod* methods,
+ int num_methods);
+
+ // Converts from Java string to std::string.
+ // This method must be called on the construction thread.
+ std::string JavaToStdString(const jstring& j_string);
+
+ private:
+ SequenceChecker thread_checker_;
+ JNIEnv* const jni_;
+};
+
+// Main class for working with Java from C++ using JNI in WebRTC.
+//
+// Example usage:
+//
+// // At initialization (e.g. in JNI_OnLoad), call JVM::Initialize.
+// JNIEnv* jni = ::base::android::AttachCurrentThread();
+// JavaVM* jvm = NULL;
+// jni->GetJavaVM(&jvm);
+// webrtc::JVM::Initialize(jvm);
+//
+// // Header (.h) file of example class called User.
+// std::unique_ptr<JNIEnvironment> env;
+// std::unique_ptr<NativeRegistration> reg;
+// std::unique_ptr<GlobalRef> obj;
+//
+// // Construction (in .cc file) of User class.
+// User::User() {
+// // Calling thread must be attached to the JVM.
+// env = JVM::GetInstance()->environment();
+// reg = env->RegisterNatives("org/webrtc/WebRtcTest", ,);
+// obj = reg->NewObject("<init>", ,);
+// }
+//
+// // Each User method can now use `reg` and `obj` and call Java functions
+// // in WebRtcTest.java, e.g. boolean init() {}.
+// bool User::Foo() {
+// jmethodID id = reg->GetMethodId("init", "()Z");
+// return obj->CallBooleanMethod(id);
+// }
+//
+// // And finally, e.g. in JNI_OnUnLoad, call JVM::Uninitialize.
+// JVM::Uninitialize();
+class JVM {
+ public:
+ // Stores global handles to the Java VM interface.
+ // Should be called once on a thread that is attached to the JVM.
+ static void Initialize(JavaVM* jvm);
+ // Like the method above but also passes the context to the ContextUtils
+ // class. This method should be used by pure-C++ Android users that can't call
+ // ContextUtils.initialize directly.
+ static void Initialize(JavaVM* jvm, jobject context);
+ // Clears handles stored in Initialize(). Must be called on same thread as
+ // Initialize().
+ static void Uninitialize();
+ // Gives access to the global Java VM interface pointer, which then can be
+ // used to create a valid JNIEnvironment object or to get a JavaClass object.
+ static JVM* GetInstance();
+
+ // Creates a JNIEnvironment object.
+ // This method returns a NULL pointer if AttachCurrentThread() has not been
+ // called successfully. Use the AttachCurrentThreadIfNeeded class if needed.
+ std::unique_ptr<JNIEnvironment> environment();
+
+ // Returns a JavaClass object given class `name`.
+ // Note that the class name must be one of the names in the static
+ // `loaded_classes` array defined in jvm_android.cc.
+ // This method must be called on the construction thread.
+ JavaClass GetClass(const char* name);
+
+ // TODO(henrika): can we make these private?
+ JavaVM* jvm() const { return jvm_; }
+
+ protected:
+ JVM(JavaVM* jvm);
+ ~JVM();
+
+ private:
+ JNIEnv* jni() const { return GetEnv(jvm_); }
+
+ SequenceChecker thread_checker_;
+ JavaVM* const jvm_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_UTILITY_INCLUDE_JVM_ANDROID_H_
diff --git a/third_party/libwebrtc/modules/utility/maybe_worker_thread.cc b/third_party/libwebrtc/modules/utility/maybe_worker_thread.cc
new file mode 100644
index 0000000000..abb52d4691
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/maybe_worker_thread.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2022 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 "modules/utility/maybe_worker_thread.h"
+
+#include <utility>
+
+#include "api/task_queue/pending_task_safety_flag.h"
+#include "api/task_queue/task_queue_base.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/event.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/task_queue.h"
+
+namespace webrtc {
+
+MaybeWorkerThread::MaybeWorkerThread(const FieldTrialsView& field_trials,
+ absl::string_view task_queue_name,
+ TaskQueueFactory* factory)
+ : owned_task_queue_(
+ field_trials.IsEnabled("WebRTC-SendPacketsOnWorkerThread")
+ ? nullptr
+ : factory->CreateTaskQueue(task_queue_name,
+ rtc::TaskQueue::Priority::NORMAL)),
+ worker_thread_(TaskQueueBase::Current()) {
+ RTC_DCHECK(worker_thread_);
+ RTC_LOG(LS_INFO) << "WebRTC-SendPacketsOnWorkerThread"
+ << (owned_task_queue_ ? " Disabled" : " Enabled");
+}
+
+MaybeWorkerThread::~MaybeWorkerThread() {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+
+ if (owned_task_queue_) {
+ // owned_task_queue_ must be a valid pointer when the task queue is
+ // destroyed since there may be tasks that use this object that run when the
+ // task queue is deleted.
+ owned_task_queue_->Delete();
+ owned_task_queue_.release();
+ }
+}
+
+void MaybeWorkerThread::RunSynchronous(absl::AnyInvocable<void() &&> task) {
+ if (owned_task_queue_) {
+ rtc::Event thread_sync_event;
+ auto closure = [&thread_sync_event, task = std::move(task)]() mutable {
+ std::move(task)();
+ thread_sync_event.Set();
+ };
+ owned_task_queue_->PostTask(std::move(closure));
+ thread_sync_event.Wait(rtc::Event::kForever);
+ } else {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ std::move(task)();
+ }
+}
+
+void MaybeWorkerThread::RunOrPost(absl::AnyInvocable<void() &&> task) {
+ if (owned_task_queue_) {
+ owned_task_queue_->PostTask(std::move(task));
+ } else {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ std::move(task)();
+ }
+}
+
+TaskQueueBase* MaybeWorkerThread::TaskQueueForDelayedTasks() const {
+ RTC_DCHECK(IsCurrent());
+ return owned_task_queue_ ? owned_task_queue_.get() : worker_thread_;
+}
+
+TaskQueueBase* MaybeWorkerThread::TaskQueueForPost() const {
+ return owned_task_queue_ ? owned_task_queue_.get() : worker_thread_;
+}
+
+bool MaybeWorkerThread::IsCurrent() const {
+ if (owned_task_queue_) {
+ return owned_task_queue_->IsCurrent();
+ }
+ return worker_thread_->IsCurrent();
+}
+
+absl::AnyInvocable<void() &&> MaybeWorkerThread::MaybeSafeTask(
+ rtc::scoped_refptr<PendingTaskSafetyFlag> flag,
+ absl::AnyInvocable<void() &&> task) {
+ if (owned_task_queue_) {
+ return task;
+ } else {
+ return SafeTask(std::move(flag), std::move(task));
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/utility/maybe_worker_thread.h b/third_party/libwebrtc/modules/utility/maybe_worker_thread.h
new file mode 100644
index 0000000000..a93a173bf6
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/maybe_worker_thread.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022 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 MODULES_UTILITY_MAYBE_WORKER_THREAD_H_
+#define MODULES_UTILITY_MAYBE_WORKER_THREAD_H_
+
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "api/field_trials_view.h"
+#include "api/sequence_checker.h"
+#include "api/task_queue/pending_task_safety_flag.h"
+#include "api/task_queue/task_queue_base.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/thread_annotations.h"
+
+namespace webrtc {
+
+// Helper class used by experiment to replace usage of the
+// RTP worker task queue owned by RtpTransportControllerSend, and the pacer task
+// queue owned by TaskQueuePacedSender with the one and only worker thread.
+// Tasks will run on the target sequence which is either the worker thread or
+// one of these task queues depending on the field trial
+// "WebRTC-SendPacketsOnWorkerThread".
+// This class is assumed to be created on the worker thread and the worker
+// thread is assumed to outlive an instance of this class.
+//
+// Experiment can be tracked in
+// https://bugs.chromium.org/p/webrtc/issues/detail?id=14502
+//
+// After experiment evaluation, this class should be deleted.
+// Calls to RunOrPost and RunSynchronous should be removed and the task should
+// be invoked immediately.
+// Instead of MaybeSafeTask a SafeTask should be used when posting tasks.
+class RTC_LOCKABLE MaybeWorkerThread {
+ public:
+ MaybeWorkerThread(const FieldTrialsView& field_trials,
+ absl::string_view task_queue_name,
+ TaskQueueFactory* factory);
+ ~MaybeWorkerThread();
+
+ // Runs `task` immediately on the worker thread if in experiment, otherwise
+ // post the task on the task queue.
+ void RunOrPost(absl::AnyInvocable<void() &&> task);
+ // Runs `task` immediately on the worker thread if in experiment, otherwise
+ // post the task on the task queue and use an even to wait for completion.
+ void RunSynchronous(absl::AnyInvocable<void() &&> task);
+
+ // Used for posting delayed or repeated tasks on the worker thread or task
+ // queue depending on the field trial. DCHECKs that this method is called on
+ // the target sequence.
+ TaskQueueBase* TaskQueueForDelayedTasks() const;
+
+ // Used when a task has to be posted from one sequence to the target
+ // sequence. A task should only be posted if a sequence hop is needed.
+ TaskQueueBase* TaskQueueForPost() const;
+
+ // Workaround to use a SafeTask only if the target sequence is the worker
+ // thread. This is used when a SafeTask can not be used because the object
+ // that posted the task is not destroyed on the target sequence. Instead, the
+ // caller has to guarantee that this MaybeWorkerThread is destroyed first
+ // since that guarantee that the posted task is deleted or run before the
+ // owning class.
+ absl::AnyInvocable<void() &&> MaybeSafeTask(
+ rtc::scoped_refptr<PendingTaskSafetyFlag> flag,
+ absl::AnyInvocable<void() &&> task);
+
+ // To implement macro RTC_DCHECK_RUN_ON.
+ // Implementation delegate to the actual used sequence.
+ bool IsCurrent() const;
+
+ private:
+ SequenceChecker sequence_checker_;
+ std::unique_ptr<TaskQueueBase, TaskQueueDeleter> owned_task_queue_;
+ TaskQueueBase* const worker_thread_;
+};
+
+} // namespace webrtc
+
+#endif // MODULES_UTILITY_MAYBE_WORKER_THREAD_H_
diff --git a/third_party/libwebrtc/modules/utility/maybe_worker_thread_unittests.cc b/third_party/libwebrtc/modules/utility/maybe_worker_thread_unittests.cc
new file mode 100644
index 0000000000..f6a981f90a
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/maybe_worker_thread_unittests.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2022 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 <memory>
+
+#include "api/sequence_checker.h"
+#include "api/task_queue/pending_task_safety_flag.h"
+#include "api/task_queue/task_queue_factory.h"
+#include "api/units/time_delta.h"
+#include "modules/utility/maybe_worker_thread.h"
+#include "rtc_base/event.h"
+#include "test/explicit_key_value_config.h"
+#include "test/gtest.h"
+#include "test/time_controller/real_time_controller.h"
+
+namespace webrtc {
+
+namespace {
+
+constexpr char kFieldTrialString[] =
+ "WebRTC-SendPacketsOnWorkerThread/Enabled/";
+
+TEST(MaybeWorkerThreadTest, RunOrPostRunOnWorkerThreadInExperiment) {
+ test::ExplicitKeyValueConfig field_trial(kFieldTrialString);
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ SequenceChecker checker;
+ bool run = false;
+ m.RunOrPost([&] {
+ EXPECT_TRUE(checker.IsCurrent());
+ run = true;
+ });
+ EXPECT_TRUE(run);
+}
+
+TEST(MaybeWorkerThreadTest, RunOrPostPostsOnTqPerDefault) {
+ test::ExplicitKeyValueConfig field_trial("");
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ SequenceChecker checker;
+ rtc::Event event;
+ m.RunOrPost([&] {
+ EXPECT_FALSE(checker.IsCurrent());
+ event.Set();
+ });
+ EXPECT_TRUE(event.Wait(TimeDelta::Seconds(10)));
+}
+
+TEST(MaybeWorkerThreadTest, RunSynchronousRunOnWorkerThreadInExperiment) {
+ test::ExplicitKeyValueConfig field_trial(kFieldTrialString);
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ SequenceChecker checker;
+ bool run = false;
+ m.RunSynchronous([&] {
+ EXPECT_TRUE(checker.IsCurrent());
+ run = true;
+ });
+ EXPECT_TRUE(run);
+}
+
+TEST(MaybeWorkerThreadTest, RunSynchronousRunOnTqPerDefault) {
+ test::ExplicitKeyValueConfig field_trial("");
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ SequenceChecker checker;
+ bool run = false;
+ m.RunSynchronous([&] {
+ EXPECT_FALSE(checker.IsCurrent());
+ run = true;
+ });
+ EXPECT_TRUE(run);
+}
+
+TEST(MaybeWorkerThreadTest, MaybeSafeTaskDoesNotReturnSafeTaskPerDefault) {
+ // We cant really test that the return value from MaybeSafeTask is a SafeTask.
+ // But we can test that the safety flag does not have more references after a
+ // call.
+ test::ExplicitKeyValueConfig field_trial("");
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ rtc::scoped_refptr<PendingTaskSafetyFlag> flag =
+ PendingTaskSafetyFlag::Create();
+ auto closure = m.MaybeSafeTask(flag, [] {});
+ EXPECT_EQ(flag->Release(), rtc::RefCountReleaseStatus::kDroppedLastRef);
+ flag.release();
+}
+
+TEST(MaybeWorkerThreadTest, MaybeSafeTaskDoesNotReturnSafeTaskInExperiment) {
+ // We cant really test that the return value from MaybeSafeTask is a SafeTask.
+ // But we can test that the safety flag does have one more references after a
+ // call.
+ test::ExplicitKeyValueConfig field_trial(kFieldTrialString);
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ rtc::scoped_refptr<PendingTaskSafetyFlag> flag =
+ PendingTaskSafetyFlag::Create();
+ auto closure = m.MaybeSafeTask(flag, [] {});
+ EXPECT_EQ(flag->Release(), rtc::RefCountReleaseStatus::kOtherRefsRemained);
+ flag.release();
+}
+
+TEST(MaybeWorkerThreadTest, IsCurrentBehavesCorrectPerDefault) {
+ test::ExplicitKeyValueConfig field_trial("");
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ EXPECT_FALSE(m.IsCurrent());
+ m.RunSynchronous([&] { EXPECT_TRUE(m.IsCurrent()); });
+}
+
+TEST(MaybeWorkerThreadTest, IsCurrentBehavesCorrectInExperiment) {
+ test::ExplicitKeyValueConfig field_trial(kFieldTrialString);
+ RealTimeController controller;
+ MaybeWorkerThread m(field_trial, "test_tq", controller.GetTaskQueueFactory());
+
+ EXPECT_TRUE(m.IsCurrent());
+ auto tq = controller.GetTaskQueueFactory()->CreateTaskQueue(
+ "tq", TaskQueueFactory::Priority::NORMAL);
+ rtc::Event event;
+ tq->PostTask([&] {
+ EXPECT_FALSE(m.IsCurrent());
+ event.Set();
+ });
+ ASSERT_TRUE(event.Wait(TimeDelta::Seconds(10)));
+}
+
+TEST(MaybeWorkerThreadTest, IsCurrentCanBeCalledInDestructorPerDefault) {
+ test::ExplicitKeyValueConfig field_trial("");
+ RealTimeController controller;
+ {
+ MaybeWorkerThread m(field_trial, "test_tq",
+ controller.GetTaskQueueFactory());
+ m.RunOrPost([&] { EXPECT_TRUE(m.IsCurrent()); });
+ }
+}
+
+TEST(MaybeWorkerThreadTest, IsCurrentCanBeCalledInDestructorInExperiment) {
+ test::ExplicitKeyValueConfig field_trial(kFieldTrialString);
+ RealTimeController controller;
+ {
+ MaybeWorkerThread m(field_trial, "test_tq",
+ controller.GetTaskQueueFactory());
+ m.RunOrPost([&] { EXPECT_TRUE(m.IsCurrent()); });
+ }
+}
+
+} // namespace
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/utility/source/helpers_android.cc b/third_party/libwebrtc/modules/utility/source/helpers_android.cc
new file mode 100644
index 0000000000..9cfee8a2af
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/source/helpers_android.cc
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#include "modules/utility/include/helpers_android.h"
+
+#include <android/log.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/platform_thread.h"
+
+#define TAG "HelpersAndroid"
+#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
+
+namespace webrtc {
+
+JNIEnv* GetEnv(JavaVM* jvm) {
+ void* env = NULL;
+ jint status = jvm->GetEnv(&env, JNI_VERSION_1_6);
+ RTC_CHECK(((env != NULL) && (status == JNI_OK)) ||
+ ((env == NULL) && (status == JNI_EDETACHED)))
+ << "Unexpected GetEnv return: " << status << ":" << env;
+ return reinterpret_cast<JNIEnv*>(env);
+}
+
+// Return a `jlong` that will correctly convert back to `ptr`. This is needed
+// because the alternative (of silently passing a 32-bit pointer to a vararg
+// function expecting a 64-bit param) picks up garbage in the high 32 bits.
+jlong PointerTojlong(void* ptr) {
+ static_assert(sizeof(intptr_t) <= sizeof(jlong),
+ "Time to rethink the use of jlongs");
+ // Going through intptr_t to be obvious about the definedness of the
+ // conversion from pointer to integral type. intptr_t to jlong is a standard
+ // widening by the static_assert above.
+ jlong ret = reinterpret_cast<intptr_t>(ptr);
+ RTC_DCHECK(reinterpret_cast<void*>(ret) == ptr);
+ return ret;
+}
+
+jmethodID GetMethodID(JNIEnv* jni,
+ jclass c,
+ const char* name,
+ const char* signature) {
+ jmethodID m = jni->GetMethodID(c, name, signature);
+ CHECK_EXCEPTION(jni) << "Error during GetMethodID: " << name << ", "
+ << signature;
+ RTC_CHECK(m) << name << ", " << signature;
+ return m;
+}
+
+jmethodID GetStaticMethodID(JNIEnv* jni,
+ jclass c,
+ const char* name,
+ const char* signature) {
+ jmethodID m = jni->GetStaticMethodID(c, name, signature);
+ CHECK_EXCEPTION(jni) << "Error during GetStaticMethodID: " << name << ", "
+ << signature;
+ RTC_CHECK(m) << name << ", " << signature;
+ return m;
+}
+
+jclass FindClass(JNIEnv* jni, const char* name) {
+ jclass c = jni->FindClass(name);
+ CHECK_EXCEPTION(jni) << "Error during FindClass: " << name;
+ RTC_CHECK(c) << name;
+ return c;
+}
+
+jobject NewGlobalRef(JNIEnv* jni, jobject o) {
+ jobject ret = jni->NewGlobalRef(o);
+ CHECK_EXCEPTION(jni) << "Error during NewGlobalRef";
+ RTC_CHECK(ret);
+ return ret;
+}
+
+void DeleteGlobalRef(JNIEnv* jni, jobject o) {
+ jni->DeleteGlobalRef(o);
+ CHECK_EXCEPTION(jni) << "Error during DeleteGlobalRef";
+}
+
+AttachThreadScoped::AttachThreadScoped(JavaVM* jvm)
+ : attached_(false), jvm_(jvm), env_(NULL) {
+ env_ = GetEnv(jvm);
+ if (!env_) {
+ // Adding debug log here so we can track down potential leaks and figure
+ // out why we sometimes see "Native thread exiting without having called
+ // DetachCurrentThread" in logcat outputs.
+ ALOGD("Attaching thread to JVM[tid=%d]", rtc::CurrentThreadId());
+ jint res = jvm->AttachCurrentThread(&env_, NULL);
+ attached_ = (res == JNI_OK);
+ RTC_CHECK(attached_) << "AttachCurrentThread failed: " << res;
+ }
+}
+
+AttachThreadScoped::~AttachThreadScoped() {
+ if (attached_) {
+ ALOGD("Detaching thread from JVM[tid=%d]", rtc::CurrentThreadId());
+ jint res = jvm_->DetachCurrentThread();
+ RTC_CHECK(res == JNI_OK) << "DetachCurrentThread failed: " << res;
+ RTC_CHECK(!GetEnv(jvm_));
+ }
+}
+
+JNIEnv* AttachThreadScoped::env() {
+ return env_;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/utility/source/jvm_android.cc b/third_party/libwebrtc/modules/utility/source/jvm_android.cc
new file mode 100644
index 0000000000..39ef12f428
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/source/jvm_android.cc
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2015 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 "modules/utility/include/jvm_android.h"
+
+#include <android/log.h>
+
+#include <memory>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/platform_thread.h"
+
+namespace mozilla {
+namespace jni {
+jclass GetClassRef(JNIEnv* aEnv, const char* aClassName);
+}
+}
+
+#define TAG "JVM"
+#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
+
+namespace webrtc {
+
+JVM* g_jvm;
+
+// TODO(henrika): add more clases here if needed.
+struct {
+ const char* name;
+ jclass clazz;
+} loaded_classes[] = {
+ {"org/webrtc/voiceengine/BuildInfo", nullptr},
+ {"org/webrtc/voiceengine/WebRtcAudioManager", nullptr},
+ {"org/webrtc/voiceengine/WebRtcAudioRecord", nullptr},
+ {"org/webrtc/voiceengine/WebRtcAudioTrack", nullptr},
+};
+
+// Android's FindClass() is trickier than usual because the app-specific
+// ClassLoader is not consulted when there is no app-specific frame on the
+// stack. Consequently, we only look up all classes once in native WebRTC.
+// http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
+void LoadClasses(JNIEnv* jni) {
+ RTC_LOG(LS_INFO) << "LoadClasses:";
+ for (auto& c : loaded_classes) {
+ ALOGD("name: %s", c.name);
+ jclass clsRef = mozilla::jni::GetClassRef(jni, c.name);
+ RTC_CHECK(clsRef) << c.name;
+ c.clazz = static_cast<jclass>(jni->NewGlobalRef(clsRef));
+ jni->DeleteLocalRef(clsRef);
+ }
+}
+
+void FreeClassReferences(JNIEnv* jni) {
+ for (auto& c : loaded_classes) {
+ jni->DeleteGlobalRef(c.clazz);
+ c.clazz = nullptr;
+ }
+}
+
+jclass LookUpClass(const char* name) {
+ for (auto& c : loaded_classes) {
+ if (strcmp(c.name, name) == 0)
+ return c.clazz;
+ }
+ RTC_CHECK(false) << "Unable to find class in lookup table";
+ return 0;
+}
+
+// JvmThreadConnector implementation.
+JvmThreadConnector::JvmThreadConnector() : attached_(false) {
+ RTC_LOG(LS_INFO) << "JvmThreadConnector::ctor";
+ JavaVM* jvm = JVM::GetInstance()->jvm();
+ RTC_CHECK(jvm);
+ JNIEnv* jni = GetEnv(jvm);
+ if (!jni) {
+ RTC_LOG(LS_INFO) << "Attaching thread to JVM";
+ JNIEnv* env = nullptr;
+ jint ret = jvm->AttachCurrentThread(&env, nullptr);
+ attached_ = (ret == JNI_OK);
+ }
+}
+
+JvmThreadConnector::~JvmThreadConnector() {
+ RTC_LOG(LS_INFO) << "JvmThreadConnector::dtor";
+ RTC_DCHECK(thread_checker_.IsCurrent());
+ if (attached_) {
+ RTC_LOG(LS_INFO) << "Detaching thread from JVM";
+ jint res = JVM::GetInstance()->jvm()->DetachCurrentThread();
+ RTC_CHECK(res == JNI_OK) << "DetachCurrentThread failed: " << res;
+ }
+}
+
+// GlobalRef implementation.
+GlobalRef::GlobalRef(JNIEnv* jni, jobject object)
+ : jni_(jni), j_object_(NewGlobalRef(jni, object)) {
+ RTC_LOG(LS_INFO) << "GlobalRef::ctor";
+}
+
+GlobalRef::~GlobalRef() {
+ RTC_LOG(LS_INFO) << "GlobalRef::dtor";
+ DeleteGlobalRef(jni_, j_object_);
+}
+
+jboolean GlobalRef::CallBooleanMethod(jmethodID methodID, ...) {
+ va_list args;
+ va_start(args, methodID);
+ jboolean res = jni_->CallBooleanMethodV(j_object_, methodID, args);
+ CHECK_EXCEPTION(jni_) << "Error during CallBooleanMethod";
+ va_end(args);
+ return res;
+}
+
+jint GlobalRef::CallIntMethod(jmethodID methodID, ...) {
+ va_list args;
+ va_start(args, methodID);
+ jint res = jni_->CallIntMethodV(j_object_, methodID, args);
+ CHECK_EXCEPTION(jni_) << "Error during CallIntMethod";
+ va_end(args);
+ return res;
+}
+
+void GlobalRef::CallVoidMethod(jmethodID methodID, ...) {
+ va_list args;
+ va_start(args, methodID);
+ jni_->CallVoidMethodV(j_object_, methodID, args);
+ CHECK_EXCEPTION(jni_) << "Error during CallVoidMethod";
+ va_end(args);
+}
+
+// NativeRegistration implementation.
+NativeRegistration::NativeRegistration(JNIEnv* jni, jclass clazz)
+ : JavaClass(jni, clazz), jni_(jni) {
+ RTC_LOG(LS_INFO) << "NativeRegistration::ctor";
+}
+
+NativeRegistration::~NativeRegistration() {
+ RTC_LOG(LS_INFO) << "NativeRegistration::dtor";
+ jni_->UnregisterNatives(j_class_);
+ CHECK_EXCEPTION(jni_) << "Error during UnregisterNatives";
+}
+
+std::unique_ptr<GlobalRef> NativeRegistration::NewObject(const char* name,
+ const char* signature,
+ ...) {
+ RTC_LOG(LS_INFO) << "NativeRegistration::NewObject";
+ va_list args;
+ va_start(args, signature);
+ jobject obj = jni_->NewObjectV(
+ j_class_, GetMethodID(jni_, j_class_, name, signature), args);
+ CHECK_EXCEPTION(jni_) << "Error during NewObjectV";
+ va_end(args);
+ return std::unique_ptr<GlobalRef>(new GlobalRef(jni_, obj));
+}
+
+// JavaClass implementation.
+jmethodID JavaClass::GetMethodId(const char* name, const char* signature) {
+ return GetMethodID(jni_, j_class_, name, signature);
+}
+
+jmethodID JavaClass::GetStaticMethodId(const char* name,
+ const char* signature) {
+ return GetStaticMethodID(jni_, j_class_, name, signature);
+}
+
+jobject JavaClass::CallStaticObjectMethod(jmethodID methodID, ...) {
+ va_list args;
+ va_start(args, methodID);
+ jobject res = jni_->CallStaticObjectMethodV(j_class_, methodID, args);
+ CHECK_EXCEPTION(jni_) << "Error during CallStaticObjectMethod";
+ return res;
+}
+
+jint JavaClass::CallStaticIntMethod(jmethodID methodID, ...) {
+ va_list args;
+ va_start(args, methodID);
+ jint res = jni_->CallStaticIntMethodV(j_class_, methodID, args);
+ CHECK_EXCEPTION(jni_) << "Error during CallStaticIntMethod";
+ return res;
+}
+
+// JNIEnvironment implementation.
+JNIEnvironment::JNIEnvironment(JNIEnv* jni) : jni_(jni) {
+ RTC_LOG(LS_INFO) << "JNIEnvironment::ctor";
+}
+
+JNIEnvironment::~JNIEnvironment() {
+ RTC_LOG(LS_INFO) << "JNIEnvironment::dtor";
+ RTC_DCHECK(thread_checker_.IsCurrent());
+}
+
+std::unique_ptr<NativeRegistration> JNIEnvironment::RegisterNatives(
+ const char* name,
+ const JNINativeMethod* methods,
+ int num_methods) {
+ RTC_LOG(LS_INFO) << "JNIEnvironment::RegisterNatives: " << name;
+ RTC_DCHECK(thread_checker_.IsCurrent());
+ jclass clazz = LookUpClass(name);
+ jni_->RegisterNatives(clazz, methods, num_methods);
+ CHECK_EXCEPTION(jni_) << "Error during RegisterNatives";
+ return std::unique_ptr<NativeRegistration>(
+ new NativeRegistration(jni_, clazz));
+}
+
+std::string JNIEnvironment::JavaToStdString(const jstring& j_string) {
+ RTC_DCHECK(thread_checker_.IsCurrent());
+ const char* jchars = jni_->GetStringUTFChars(j_string, nullptr);
+ CHECK_EXCEPTION(jni_);
+ const int size = jni_->GetStringUTFLength(j_string);
+ CHECK_EXCEPTION(jni_);
+ std::string ret(jchars, size);
+ jni_->ReleaseStringUTFChars(j_string, jchars);
+ CHECK_EXCEPTION(jni_);
+ return ret;
+}
+
+// static
+void JVM::Initialize(JavaVM* jvm) {
+ if (g_jvm) {
+ return;
+ }
+ g_jvm = new JVM(jvm);
+}
+
+void JVM::Initialize(JavaVM* jvm, jobject context) {
+ Initialize(jvm);
+
+ // Pass in the context to the new ContextUtils class.
+ JNIEnv* jni = g_jvm->jni();
+ jclass context_utils = FindClass(jni, "org/webrtc/ContextUtils");
+ jmethodID initialize_method = jni->GetStaticMethodID(
+ context_utils, "initialize", "(Landroid/content/Context;)V");
+ jni->CallStaticVoidMethod(context_utils, initialize_method, context);
+}
+
+// static
+void JVM::Uninitialize() {
+ RTC_LOG(LS_INFO) << "JVM::Uninitialize";
+ RTC_DCHECK(g_jvm);
+ delete g_jvm;
+ g_jvm = nullptr;
+}
+
+// static
+JVM* JVM::GetInstance() {
+ RTC_DCHECK(g_jvm);
+ return g_jvm;
+}
+
+JVM::JVM(JavaVM* jvm) : jvm_(jvm) {
+ RTC_LOG(LS_INFO) << "JVM::JVM";
+ RTC_CHECK(jni()) << "AttachCurrentThread() must be called on this thread.";
+ LoadClasses(jni());
+}
+
+JVM::~JVM() {
+ RTC_LOG(LS_INFO) << "JVM::~JVM";
+ RTC_DCHECK(thread_checker_.IsCurrent());
+ FreeClassReferences(jni());
+}
+
+std::unique_ptr<JNIEnvironment> JVM::environment() {
+ RTC_LOG(LS_INFO) << "JVM::environment";
+ ;
+ // The JNIEnv is used for thread-local storage. For this reason, we cannot
+ // share a JNIEnv between threads. If a piece of code has no other way to get
+ // its JNIEnv, we should share the JavaVM, and use GetEnv to discover the
+ // thread's JNIEnv. (Assuming it has one, if not, use AttachCurrentThread).
+ // See // http://developer.android.com/training/articles/perf-jni.html.
+ JNIEnv* jni = GetEnv(jvm_);
+ if (!jni) {
+ RTC_LOG(LS_ERROR)
+ << "AttachCurrentThread() has not been called on this thread";
+ return std::unique_ptr<JNIEnvironment>();
+ }
+ return std::unique_ptr<JNIEnvironment>(new JNIEnvironment(jni));
+}
+
+JavaClass JVM::GetClass(const char* name) {
+ RTC_LOG(LS_INFO) << "JVM::GetClass: " << name;
+ RTC_DCHECK(thread_checker_.IsCurrent());
+ return JavaClass(jni(), LookUpClass(name));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/modules/utility/utility_gn/moz.build b/third_party/libwebrtc/modules/utility/utility_gn/moz.build
new file mode 100644
index 0000000000..b932f5da73
--- /dev/null
+++ b/third_party/libwebrtc/modules/utility/utility_gn/moz.build
@@ -0,0 +1,229 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+ ### This moz.build was AUTOMATICALLY GENERATED from a GN config, ###
+ ### DO NOT edit it by hand. ###
+
+COMPILE_FLAGS["OS_INCLUDES"] = []
+AllowCompilerWarnings()
+
+DEFINES["ABSL_ALLOCATOR_NOTHROW"] = "1"
+DEFINES["RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY"] = True
+DEFINES["RTC_ENABLE_VP9"] = True
+DEFINES["WEBRTC_ENABLE_PROTOBUF"] = "0"
+DEFINES["WEBRTC_LIBRARY_IMPL"] = True
+DEFINES["WEBRTC_MOZILLA_BUILD"] = True
+DEFINES["WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS"] = "0"
+DEFINES["WEBRTC_STRICT_FIELD_TRIALS"] = "0"
+
+FINAL_LIBRARY = "webrtc"
+
+
+LOCAL_INCLUDES += [
+ "!/ipc/ipdl/_ipdlheaders",
+ "!/third_party/libwebrtc/gen",
+ "/ipc/chromium/src",
+ "/third_party/libwebrtc/",
+ "/third_party/libwebrtc/third_party/abseil-cpp/",
+ "/tools/profiler/public"
+]
+
+UNIFIED_SOURCES += [
+ "/third_party/libwebrtc/modules/utility/maybe_worker_thread.cc"
+]
+
+if not CONFIG["MOZ_DEBUG"]:
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "0"
+ DEFINES["NDEBUG"] = True
+ DEFINES["NVALGRIND"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1":
+
+ DEFINES["DYNAMIC_ANNOTATIONS_ENABLED"] = "1"
+
+if CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["ANDROID"] = True
+ DEFINES["ANDROID_NDK_VERSION_ROLL"] = "r22_1"
+ DEFINES["HAVE_SYS_UIO_H"] = True
+ DEFINES["WEBRTC_ANDROID"] = True
+ DEFINES["WEBRTC_ANDROID_OPENSLES"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_GNU_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+ OS_LIBS += [
+ "log"
+ ]
+
+ UNIFIED_SOURCES += [
+ "/third_party/libwebrtc/modules/utility/source/helpers_android.cc"
+ ]
+
+if CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["WEBRTC_MAC"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_LIBCPP_HAS_NO_ALIGNED_ALLOCATION"] = True
+ DEFINES["__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES"] = "0"
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_NSS_CERTS"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_UDEV"] = True
+ DEFINES["WEBRTC_LINUX"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["USE_GLIB"] = "1"
+ DEFINES["USE_OZONE"] = "1"
+ DEFINES["USE_X11"] = "1"
+ DEFINES["WEBRTC_BSD"] = True
+ DEFINES["WEBRTC_POSIX"] = True
+ DEFINES["_FILE_OFFSET_BITS"] = "64"
+ DEFINES["_LARGEFILE64_SOURCE"] = True
+ DEFINES["_LARGEFILE_SOURCE"] = True
+ DEFINES["__STDC_CONSTANT_MACROS"] = True
+ DEFINES["__STDC_FORMAT_MACROS"] = True
+
+if CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["CERT_CHAIN_PARA_HAS_EXTRA_FIELDS"] = True
+ DEFINES["NOMINMAX"] = True
+ DEFINES["NTDDI_VERSION"] = "0x0A000000"
+ DEFINES["PSAPI_VERSION"] = "2"
+ DEFINES["UNICODE"] = True
+ DEFINES["USE_AURA"] = "1"
+ DEFINES["WEBRTC_WIN"] = True
+ DEFINES["WIN32"] = True
+ DEFINES["WIN32_LEAN_AND_MEAN"] = True
+ DEFINES["WINAPI_FAMILY"] = "WINAPI_FAMILY_DESKTOP_APP"
+ DEFINES["WINVER"] = "0x0A00"
+ DEFINES["_ATL_NO_OPENGL"] = True
+ DEFINES["_CRT_RAND_S"] = True
+ DEFINES["_CRT_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_ENABLE_EXTENDED_ALIGNED_STORAGE"] = True
+ DEFINES["_HAS_EXCEPTIONS"] = "0"
+ DEFINES["_HAS_NODISCARD"] = True
+ DEFINES["_SCL_SECURE_NO_DEPRECATE"] = True
+ DEFINES["_SECURE_ATL"] = True
+ DEFINES["_UNICODE"] = True
+ DEFINES["_WIN32_WINNT"] = "0x0A00"
+ DEFINES["_WINDOWS"] = True
+ DEFINES["__STD_C"] = True
+
+ OS_LIBS += [
+ "winmm"
+ ]
+
+if CONFIG["CPU_ARCH"] == "aarch64":
+
+ DEFINES["WEBRTC_ARCH_ARM64"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["CPU_ARCH"] == "arm":
+
+ CXXFLAGS += [
+ "-mfpu=neon"
+ ]
+
+ DEFINES["WEBRTC_ARCH_ARM"] = True
+ DEFINES["WEBRTC_ARCH_ARM_V7"] = True
+ DEFINES["WEBRTC_HAS_NEON"] = True
+
+if CONFIG["CPU_ARCH"] == "mips32":
+
+ DEFINES["MIPS32_LE"] = True
+ DEFINES["MIPS_FPU_LE"] = True
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["CPU_ARCH"] == "mips64":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["CPU_ARCH"] == "x86":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["CPU_ARCH"] == "x86_64":
+
+ DEFINES["WEBRTC_ENABLE_AVX2"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Android":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Darwin":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "OpenBSD":
+
+ DEFINES["_DEBUG"] = True
+
+if CONFIG["MOZ_DEBUG"] == "1" and CONFIG["OS_TARGET"] == "WINNT":
+
+ DEFINES["_HAS_ITERATOR_DEBUGGING"] = "0"
+
+if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["USE_X11"] = "1"
+
+if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Android":
+
+ OS_LIBS += [
+ "android_support",
+ "unwind"
+ ]
+
+if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Android":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ OS_LIBS += [
+ "android_support"
+ ]
+
+if CONFIG["CPU_ARCH"] == "aarch64" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["CPU_ARCH"] == "arm" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["CPU_ARCH"] == "x86" and CONFIG["OS_TARGET"] == "Linux":
+
+ CXXFLAGS += [
+ "-msse2"
+ ]
+
+ DEFINES["_GNU_SOURCE"] = True
+
+if CONFIG["CPU_ARCH"] == "x86_64" and CONFIG["OS_TARGET"] == "Linux":
+
+ DEFINES["_GNU_SOURCE"] = True
+
+Library("utility_gn")