plugins {
id 'com.android.library'
+ id 'jacoco'
}
android {
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
+ debug {
+ testCoverageEnabled(true)
+ }
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
implementation 'com.google.android.material:material:1.4.0'
implementation 'org.webrtc:google-webrtc:1.0.32006'
+ testImplementation 'junit:junit:4.13.2'
+ testImplementation 'androidx.test:core:1.5.0'
+ testImplementation 'org.mockito:mockito-inline:3.4.0'
+
androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
androidTestImplementation project(path: ':android:aitt')
}
+
+task jacocoReport(type: JacocoReport) {
+ group "Coverage"
+ description "Generate XML/HTML code coverage reports for coverage.ec"
+
+ reports {
+ xml.enabled = true
+ html.enabled = true
+ }
+
+ getSourceDirectories().setFrom("${project.projectDir}/src/main/java")
+ def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
+ getClassDirectories().setFrom(
+ fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: fileFilter),
+ fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: fileFilter))
+ getExecutionData().setFrom(
+ fileTree(dir: "${buildDir}/outputs/code_coverage", includes: ['*.ec']))
+}
try {
String ip = wifiIpAddress();
+ Log.d(TAG, "Final WiFi IP = " + ip);
Aitt serverSubscriber = new Aitt(appContext, AITT_WEBRTC_SERVER_ID, ip, true);
serverSubscriber.connect(brokerIp, PORT);
Looper.loop();
Log.i(TAG, "A looper is finished.");
+
+ clientPublisherStream.disconnect();
+
+ serverSubscriberStream.stop();
} catch (Exception e) {
fail("Failed testWebRTCBasicStreaming, (" + e + ")");
}
LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);
for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
String targetIp = linkAddress.toString();
+ Log.d(TAG, "Searched IP = " + targetIp);
if (targetIp.contains("192.168")) {
StringTokenizer tokenizer = new StringTokenizer(targetIp, "/");
if (tokenizer.hasMoreTokens())
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.samsung.android.modules.webrtc">
+
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission
+ android:name="android.permission.READ_EXTERNAL_STORAGE"
+ android:maxSdkVersion="29" />
+ <uses-permission
+ android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+ android:maxSdkVersion="29" />
+
+ <application android:requestLegacyExternalStorage="true" />
+
+</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.samsung.android.modules.webrtc">
- <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true" />
+
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission
+ android:name="android.permission.READ_EXTERNAL_STORAGE"
+ android:maxSdkVersion="29" />
+ <uses-permission
+ android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+ android:maxSdkVersion="29" />
+
+ <application android:requestLegacyExternalStorage="true" />
+
</manifest>
* @param appContext Application context creating webRTC instance
*/
public WebRTC(Context appContext) {
+ if (appContext == null)
+ throw new IllegalArgumentException("App context is null.");
+
this.appContext = appContext;
this.isReceiver = false;
}
*
* @param cb aitt callback registered to receive a webrtc data
*/
- public void registerDataCallback(ReceiveDataCallback cb) {
+ void registerDataCallback(ReceiveDataCallback cb) {
+ if (cb == null)
+ throw new IllegalArgumentException("Callback is null.");
+
this.dataCallback = cb;
}
/**
* Method to establish a socket connection with peer node
*/
- public void connect() {
+ void connect() {
initialize();
}
this.receiverIP = receiverIP;
this.receiverPort = receiverPort;
initialize();
+ Log.i(TAG, "A WebRTC client is connected.");
}
/**
initializePeerConnectionFactory();
initializePeerConnections();
+ Log.i(TAG, "Peer connections are initialized.");
+
if (!isReceiver) {
createVideoTrack();
addVideoTrack();
dataCallback.pushData(array);
} else {
String message = StandardCharsets.UTF_8.decode(buffer.data).toString();
- handlelargeMessage(message, buffer);
+ handleLargeMessage(message, buffer);
}
}
});
return factory.createPeerConnection(rtcConfig, pcConstraints, pcObserver);
}
- private void handlelargeMessage(String message, DataChannel.Buffer buffer) {
+ private void handleLargeMessage(String message, DataChannel.Buffer buffer) {
if (EOF_MESSAGE.equals(message)) {
Log.d(TAG, "Byte array size: " + baos.size());
dataCallback.pushData(baos.toByteArray());
createSocket();
invokeSendMessage();
+ Log.i(TAG, "The SDP thread of WebRTC client started.");
while (isRunning) {
try {
}
outStream = new ObjectOutputStream(socket.getOutputStream());
inputStream = new ObjectInputStream(socket.getInputStream());
+ Log.i(TAG, "A WebRTC client socket and input/output streams are created.");
} catch (Exception e) {
Log.e(TAG, "Error during create socket", e);
}
* @param appContext Application context of the app creating WebRTCServer instance
*/
public WebRTCServer(Context appContext) {
+ if (appContext == null)
+ throw new IllegalArgumentException("App context is null.");
+
this.appContext = appContext;
}
--- /dev/null
+package android.util;
+
+public class Log {
+ public static int d(String tag, String msg) {
+ System.out.println("DEBUG: " + tag + ": " + msg);
+ return 0;
+ }
+
+ public static int i(String tag, String msg) {
+ System.out.println("INFO: " + tag + ": " + msg);
+ return 0;
+ }
+
+ public static int w(String tag, String msg) {
+ System.out.println("WARN: " + tag + ": " + msg);
+ return 0;
+ }
+
+ public static int e(String tag, String msg) {
+ System.out.println("ERROR: " + tag + ": " + msg);
+ return 0;
+ }
+}
--- /dev/null
+package com.samsung.android.modules.webrtc;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.util.Log;
+
+public class WebRTCUnitTest {
+ @Mock
+ private final Context context = mock(Context.class);
+
+ private static MockedStatic<Log> mockedLog;
+
+ @BeforeClass
+ public static void beforeClass() {
+ mockedLog = mockStatic(Log.class);
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ mockedLog.close();
+ }
+
+ @Test
+ public void testWebRTCServerConstructor_P() {
+ WebRTCServer webRTCServer = new WebRTCServer(context);
+ assertNotNull("WebRTCServer instance not null", webRTCServer);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testWebRTCServerConstructor_N() throws IllegalArgumentException {
+ WebRTCServer webRTCServer = new WebRTCServer(null);
+ assertNotNull("WebRTCServer instance not null", webRTCServer);
+ }
+
+ @Test
+ public void testWebRTCServerStart_P() {
+ WebRTCServer webRTCServer = new WebRTCServer(context);
+ webRTCServer.setDataCallback(frame -> {
+ });
+ webRTCServer.start();
+ }
+
+ @Test
+ public void testWebRTCServerStart_N() {
+ when(Log.e(any(String.class), any(String.class))).thenReturn(any(Integer.class), any(Integer.class));
+ WebRTCServer webRTCServer = new WebRTCServer(context);
+ webRTCServer.setDataCallback(null);
+ assertEquals("Fail to start a WebRTC server", -1, webRTCServer.start());
+ }
+
+ @Test
+ public void testWebRTCServerStop_P() {
+ WebRTCServer webRTCServer = new WebRTCServer(context);
+ webRTCServer.setDataCallback(frame -> {
+ });
+ webRTCServer.start();
+
+ webRTCServer.stop();
+ }
+
+ @Test
+ public void testWebRTCConstructor_P() {
+ WebRTC webRTC = new WebRTC(context);
+ assertNotNull("WebRTC instance not null", webRTC);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testWebRTCConstructor_N() throws IllegalArgumentException {
+ WebRTC webRTC = new WebRTC(null);
+ assertNotNull("WebRTC instance not null", webRTC);
+ }
+}
dependencies {
classpath "com.android.tools.build:gradle:4.2.0"
+ classpath "org.jacoco:org.jacoco.core:0.8.7"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}