From b244727265caf06256e4112d30b681e5ac4c428a Mon Sep 17 00:00:00 2001 From: Byoungchan Lee Date: Thu, 13 Jun 2024 21:55:41 +0900 Subject: [PATCH] [Android] Add RtcError class and use it in RtpTransceiver.setCodecPreferences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL modifies RtpTransceiver.setCodecPreferences to return RtcError instead of void, making it easier to handle errors when setting codec preferences. To achieve this, new RtcException and RtcError classes are introduced to represent errors in WebRTC, mimicking api/rtc_error.h in C++. Bug: webrtc:42225493 Change-Id: I0f4c6e56f8f2af3353915a41084f6b7b46d793d4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/352900 Reviewed-by: Zoé Lepaul Commit-Queue: Zoé Lepaul Cr-Commit-Position: refs/heads/main@{#42476} --- sdk/android/BUILD.gn | 10 +++ .../api/org/webrtc/RtpTransceiver.java | 6 +- .../src/org/webrtc/RtpCapabilitiesTest.java | 15 ++++- sdk/android/src/java/org/webrtc/RtcError.java | 61 +++++++++++++++++++ .../src/java/org/webrtc/RtcException.java | 22 +++++++ sdk/android/src/jni/pc/rtp_transceiver.cc | 20 ++++-- 6 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 sdk/android/src/java/org/webrtc/RtcError.java create mode 100644 sdk/android/src/java/org/webrtc/RtcException.java diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index bfaebad8d8..be84a6158b 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -164,6 +164,8 @@ if (is_android) { "src/java/org/webrtc/JniCommon.java", "src/java/org/webrtc/JniHelper.java", "src/java/org/webrtc/RefCountDelegate.java", + "src/java/org/webrtc/RtcError.java", + "src/java/org/webrtc/RtcException.java", "src/java/org/webrtc/WebRtcClassLoader.java", ] @@ -765,7 +767,9 @@ if (current_os == "linux" || is_android) { deps = [ ":base_jni", ":generated_external_classes_jni", + ":generated_external_classes_jni", ":generated_peerconnection_jni", + ":generated_rtcerror_jni", ":logging_jni", ":native_api_jni", ":native_api_stacktrace", @@ -1389,6 +1393,12 @@ if (current_os == "linux" || is_android) { jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" } + generate_jni("generated_rtcerror_jni") { + sources = [ "src/java/org/webrtc/RtcError.java" ] + namespace = "webrtc::jni" + jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h" + } + generate_jni("generated_peerconnection_jni") { sources = [ "api/org/webrtc/AddIceObserver.java", diff --git a/sdk/android/api/org/webrtc/RtpTransceiver.java b/sdk/android/api/org/webrtc/RtpTransceiver.java index d2ba733db0..89299cef59 100644 --- a/sdk/android/api/org/webrtc/RtpTransceiver.java +++ b/sdk/android/api/org/webrtc/RtpTransceiver.java @@ -215,9 +215,9 @@ public class RtpTransceiver { nativeStopInternal(nativeRtpTransceiver); } - public void setCodecPreferences(List codecs) { + public RtcError setCodecPreferences(List codecs) { checkRtpTransceiverExists(); - nativeSetCodecPreferences(nativeRtpTransceiver, codecs); + return nativeSetCodecPreferences(nativeRtpTransceiver, codecs); } /** @@ -268,6 +268,6 @@ public class RtpTransceiver { private static native void nativeStopStandard(long rtpTransceiver); private static native boolean nativeSetDirection( long rtpTransceiver, RtpTransceiverDirection rtpTransceiverDirection); - private static native void nativeSetCodecPreferences( + private static native RtcError nativeSetCodecPreferences( long rtpTransceiver, List codecs); } diff --git a/sdk/android/instrumentationtests/src/org/webrtc/RtpCapabilitiesTest.java b/sdk/android/instrumentationtests/src/org/webrtc/RtpCapabilitiesTest.java index 961ecd5c70..e04b2361dd 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/RtpCapabilitiesTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/RtpCapabilitiesTest.java @@ -158,7 +158,8 @@ public class RtpCapabilitiesTest { assertNotNull(targetCodec); - transceiver.setCodecPreferences(Arrays.asList(targetCodec)); + RtcError result = transceiver.setCodecPreferences(Arrays.asList(targetCodec)); + assertTrue(result.isSuccess()); SdpObserverLatch sdpLatch = new SdpObserverLatch(); pc.createOffer(sdpLatch, new MediaConstraints()); @@ -183,6 +184,18 @@ public class RtpCapabilitiesTest { String expected = "a=rtpmap:" + targetPayload + " " + targetCodec.name + "/" + targetCodec.getClockRate(); assertEquals(expected, rtpMap); + + // Set an invalid codec preference and check that an error is returned. + RtpCapabilities audioCapabilities = + factory.getRtpSenderCapabilities(MediaStreamTrack.MediaType.MEDIA_TYPE_AUDIO); + assertNotNull(audioCapabilities); + RtpCapabilities.CodecCapability audioCodec = audioCapabilities.getCodecs().get(0); + + result = transceiver.setCodecPreferences(Arrays.asList(audioCodec)); + assertTrue(result.isError()); + Throwable resultException = result.error(); + assertTrue(resultException instanceof RtcException); + assertTrue(resultException.getMessage().startsWith("Invalid codec preferences:")); } private List getMediaDescriptions(String[] sdpDescriptionLines) { diff --git a/sdk/android/src/java/org/webrtc/RtcError.java b/sdk/android/src/java/org/webrtc/RtcError.java new file mode 100644 index 0000000000..854541c82f --- /dev/null +++ b/sdk/android/src/java/org/webrtc/RtcError.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 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; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * RtcError class is used to handle errors obtainable from WebRTC operations. + */ +public class RtcError { + private final RtcException error; + + private RtcError(RtcException error) { + this.error = error; + } + + /** Creates a RtcError with success */ + @CalledByNative + public static RtcError success() { + return new RtcError(null); + } + + /** Creates a RtcError with an error */ + @CalledByNative + public static RtcError error(@NonNull String error) { + return new RtcError(new RtcException(error)); + } + + public boolean isSuccess() { + return error == null; + } + + public boolean isError() { + return error != null; + } + + /** + * Retrieve the error from the WebRTC operation. + * If the operation was successful, this will return null. + */ + @Nullable + public RtcException error() { + return error; + } + + /** Throws the error if it is not null. */ + public void throwError() { + if (error != null) { + throw error; + } + } +} diff --git a/sdk/android/src/java/org/webrtc/RtcException.java b/sdk/android/src/java/org/webrtc/RtcException.java new file mode 100644 index 0000000000..d2dafbae2d --- /dev/null +++ b/sdk/android/src/java/org/webrtc/RtcException.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 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; + +/** + * RtcException represents exceptions that are specific to the WebRTC library. Refer to the file + * api/rtc_error.h for more information. + */ +public class RtcException extends RuntimeException { + + public RtcException(String message) { + super(message); + } +} diff --git a/sdk/android/src/jni/pc/rtp_transceiver.cc b/sdk/android/src/jni/pc/rtp_transceiver.cc index 748dbb7f10..4d5b00d79d 100644 --- a/sdk/android/src/jni/pc/rtp_transceiver.cc +++ b/sdk/android/src/jni/pc/rtp_transceiver.cc @@ -13,6 +13,7 @@ #include #include "sdk/android/generated_peerconnection_jni/RtpTransceiver_jni.h" +#include "sdk/android/generated_rtcerror_jni/RtcError_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/media_stream_track.h" @@ -140,15 +141,22 @@ ScopedJavaLocalRef JNI_RtpTransceiver_CurrentDirection( : nullptr; } -void JNI_RtpTransceiver_SetCodecPreferences( +ScopedJavaLocalRef JNI_RtpTransceiver_SetCodecPreferences( JNIEnv* jni, jlong j_rtp_transceiver_pointer, const JavaParamRef& j_codecs) { - std::vector codecs = - JavaListToNativeVector( - jni, j_codecs, &JavaToNativeRtpCodecCapability); - reinterpret_cast(j_rtp_transceiver_pointer) - ->SetCodecPreferences(codecs); + std::vector codecs; + if (j_codecs) { + codecs = JavaListToNativeVector( + jni, j_codecs, &JavaToNativeRtpCodecCapability); + } + RTCError error = + reinterpret_cast(j_rtp_transceiver_pointer) + ->SetCodecPreferences(codecs); + if (!error.ok()) { + return Java_RtcError_error(jni, NativeToJavaString(jni, error.message())); + } + return Java_RtcError_success(jni); } void JNI_RtpTransceiver_StopInternal(JNIEnv* jni,