Replace LooperExecutor with built-in class in Android AppRTC Demo

LooperExecutor is only truly needed in WebSocketChannelClient because of
WebSocketClient from autobanh requiring thread to have a looper. So
LooperExecutor was left there but replaced everywhere else with built-in
singleThreadExecutor/singleThreadScheduledExecutor.

Motivation behind this change is that built-in class behaves better
under testing environment and doesn't require hacky
RobolectricLooperExecutor.

Review-Url: https://codereview.webrtc.org/1992213002
Cr-Commit-Position: refs/heads/master@{#12823}
This commit is contained in:
sakal
2016-05-20 02:41:02 -07:00
committed by Commit bot
parent 04ebea3629
commit 7cf11476b9
10 changed files with 79 additions and 199 deletions

View File

@ -10,11 +10,6 @@
package org.appspot.apprtc; package org.appspot.apprtc;
import org.appspot.apprtc.AppRTCClient.RoomConnectionParameters;
import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionParameters;
import org.appspot.apprtc.util.LooperExecutor;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
@ -30,12 +25,16 @@ import android.view.Window;
import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams;
import android.widget.Toast; import android.widget.Toast;
import org.appspot.apprtc.AppRTCClient.RoomConnectionParameters;
import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionParameters;
import org.appspot.apprtc.util.LooperExecutor;
import org.webrtc.EglBase; import org.webrtc.EglBase;
import org.webrtc.IceCandidate; import org.webrtc.IceCandidate;
import org.webrtc.PeerConnectionFactory; import org.webrtc.PeerConnectionFactory;
import org.webrtc.RendererCommon.ScalingType;
import org.webrtc.SessionDescription; import org.webrtc.SessionDescription;
import org.webrtc.StatsReport; import org.webrtc.StatsReport;
import org.webrtc.RendererCommon.ScalingType;
import org.webrtc.SurfaceViewRenderer; import org.webrtc.SurfaceViewRenderer;
/** /**
@ -245,7 +244,7 @@ public class CallActivity extends Activity
appRtcClient = new WebSocketRTCClient(this, new LooperExecutor()); appRtcClient = new WebSocketRTCClient(this, new LooperExecutor());
} else { } else {
Log.i(TAG, "Using DirectRTCClient because room name looks like an IP."); Log.i(TAG, "Using DirectRTCClient because room name looks like an IP.");
appRtcClient = new DirectRTCClient(this, new LooperExecutor()); appRtcClient = new DirectRTCClient(this);
} }
// Create connection parameters. // Create connection parameters.
roomConnectionParameters = new RoomConnectionParameters( roomConnectionParameters = new RoomConnectionParameters(
@ -314,9 +313,6 @@ public class CallActivity extends Activity
} }
activityRunning = false; activityRunning = false;
rootEglBase.release(); rootEglBase.release();
if (cpuMonitor != null) {
cpuMonitor.release();
}
super.onDestroy(); super.onDestroy();
} }

View File

@ -23,8 +23,9 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.Executors;
import org.appspot.apprtc.util.LooperExecutor; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** /**
* Simple CPU monitor. The caller creates a CpuMonitor object which can then * Simple CPU monitor. The caller creates a CpuMonitor object which can then
@ -85,7 +86,7 @@ class CpuMonitor {
// CPU frequency in percentage from maximum. // CPU frequency in percentage from maximum.
private final MovingAverage frequencyScale; private final MovingAverage frequencyScale;
private LooperExecutor executor; private ScheduledExecutorService executor;
private long lastStatLogTimeMs; private long lastStatLogTimeMs;
private long[] cpuFreqMax; private long[] cpuFreqMax;
private int cpusPresent; private int cpusPresent;
@ -159,33 +160,21 @@ class CpuMonitor {
frequencyScale = new MovingAverage(MOVING_AVERAGE_SAMPLES); frequencyScale = new MovingAverage(MOVING_AVERAGE_SAMPLES);
lastStatLogTimeMs = SystemClock.elapsedRealtime(); lastStatLogTimeMs = SystemClock.elapsedRealtime();
executor = new LooperExecutor();
executor.requestStart();
scheduleCpuUtilizationTask(); scheduleCpuUtilizationTask();
} }
public void release() {
if (executor != null) {
Log.d(TAG, "release");
executor.cancelScheduledTasks();
executor.requestStop();
executor = null;
}
}
public void pause() { public void pause() {
if (executor != null) { if (executor != null) {
Log.d(TAG, "pause"); Log.d(TAG, "pause");
executor.cancelScheduledTasks(); executor.shutdownNow();
executor = null;
} }
} }
public void resume() { public void resume() {
if (executor != null) { Log.d(TAG, "resume");
Log.d(TAG, "resume"); resetStat();
resetStat(); scheduleCpuUtilizationTask();
scheduleCpuUtilizationTask();
}
} }
public synchronized void reset() { public synchronized void reset() {
@ -209,13 +198,18 @@ class CpuMonitor {
} }
private void scheduleCpuUtilizationTask() { private void scheduleCpuUtilizationTask() {
executor.cancelScheduledTasks(); if (executor != null) {
executor.shutdownNow();
executor = null;
}
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(new Runnable() { executor.scheduleAtFixedRate(new Runnable() {
@Override @Override
public void run() { public void run() {
cpuUtilizationTask(); cpuUtilizationTask();
} }
}, CPU_STAT_SAMPLE_PERIOD_MS); }, 0, CPU_STAT_SAMPLE_PERIOD_MS, TimeUnit.MILLISECONDS);
} }
private void cpuUtilizationTask() { private void cpuUtilizationTask() {

View File

@ -12,7 +12,6 @@ package org.appspot.apprtc;
import android.util.Log; import android.util.Log;
import org.appspot.apprtc.util.LooperExecutor;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -21,6 +20,8 @@ import org.webrtc.PeerConnection;
import org.webrtc.SessionDescription; import org.webrtc.SessionDescription;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -52,7 +53,7 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
+ "(:(\\d+))?" + "(:(\\d+))?"
); );
private final LooperExecutor executor; private final ExecutorService executor;
private final SignalingEvents events; private final SignalingEvents events;
private TCPChannelClient tcpClient; private TCPChannelClient tcpClient;
private RoomConnectionParameters connectionParameters; private RoomConnectionParameters connectionParameters;
@ -64,11 +65,10 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
// All alterations of the room state should be done from inside the looper thread. // All alterations of the room state should be done from inside the looper thread.
private ConnectionState roomState; private ConnectionState roomState;
public DirectRTCClient(SignalingEvents events, LooperExecutor looperExecutor) { public DirectRTCClient(SignalingEvents events) {
this.events = events; this.events = events;
executor = looperExecutor;
executor.requestStart(); executor = Executors.newSingleThreadExecutor();
roomState = ConnectionState.NEW; roomState = ConnectionState.NEW;
} }
@ -148,6 +148,7 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
tcpClient.disconnect(); tcpClient.disconnect();
tcpClient = null; tcpClient = null;
} }
executor.shutdown();
} }
@Override @Override
@ -295,13 +296,11 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
@Override @Override
public void onTCPError(String description) { public void onTCPError(String description) {
reportError("TCP connection error: " + description); reportError("TCP connection error: " + description);
executor.requestStop();
} }
@Override @Override
public void onTCPClose() { public void onTCPClose() {
events.onChannelClose(); events.onChannelClose();
executor.requestStop();
} }
// -------------------------------------------------------------------- // --------------------------------------------------------------------

View File

@ -16,7 +16,6 @@ import android.os.Environment;
import android.util.Log; import android.util.Log;
import org.appspot.apprtc.AppRTCClient.SignalingParameters; import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import org.appspot.apprtc.util.LooperExecutor;
import org.webrtc.AudioTrack; import org.webrtc.AudioTrack;
import org.webrtc.CameraEnumerationAndroid; import org.webrtc.CameraEnumerationAndroid;
import org.webrtc.DataChannel; import org.webrtc.DataChannel;
@ -46,6 +45,9 @@ import java.util.EnumSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -88,7 +90,7 @@ public class PeerConnectionClient {
private static final PeerConnectionClient instance = new PeerConnectionClient(); private static final PeerConnectionClient instance = new PeerConnectionClient();
private final PCObserver pcObserver = new PCObserver(); private final PCObserver pcObserver = new PCObserver();
private final SDPObserver sdpObserver = new SDPObserver(); private final SDPObserver sdpObserver = new SDPObserver();
private final LooperExecutor executor; private final ScheduledExecutorService executor;
private PeerConnectionFactory factory; private PeerConnectionFactory factory;
private PeerConnection peerConnection; private PeerConnection peerConnection;
@ -219,11 +221,10 @@ public class PeerConnectionClient {
} }
private PeerConnectionClient() { private PeerConnectionClient() {
executor = new LooperExecutor(); // Executor thread is started once in private ctor and is used for all
// Looper thread is started once in private ctor and is used for all
// peer connection API calls to ensure new peer connection factory is // peer connection API calls to ensure new peer connection factory is
// created on the same thread as previously destroyed factory. // created on the same thread as previously destroyed factory.
executor.requestStart(); executor = Executors.newSingleThreadScheduledExecutor();
} }
public static PeerConnectionClient getInstance() { public static PeerConnectionClient getInstance() {

View File

@ -12,7 +12,7 @@ package org.appspot.apprtc;
import android.util.Log; import android.util.Log;
import org.appspot.apprtc.util.LooperExecutor; import org.webrtc.ThreadUtils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -22,6 +22,7 @@ import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
/** /**
* Replacement for WebSocketChannelClient for direct communication between two IP addresses. Handles * Replacement for WebSocketChannelClient for direct communication between two IP addresses. Handles
@ -34,7 +35,8 @@ import java.net.UnknownHostException;
public class TCPChannelClient { public class TCPChannelClient {
private static final String TAG = "TCPChannelClient"; private static final String TAG = "TCPChannelClient";
private final LooperExecutor executor; private final ExecutorService executor;
private final ThreadUtils.ThreadChecker executorThreadCheck;
private final TCPChannelEvents eventListener; private final TCPChannelEvents eventListener;
private TCPSocket socket; private TCPSocket socket;
@ -58,8 +60,10 @@ public class TCPChannelClient {
* @param port Port to listen on or connect to. * @param port Port to listen on or connect to.
*/ */
public TCPChannelClient( public TCPChannelClient(
LooperExecutor executor, TCPChannelEvents eventListener, String ip, int port) { ExecutorService executor, TCPChannelEvents eventListener, String ip, int port) {
this.executor = executor; this.executor = executor;
executorThreadCheck = new ThreadUtils.ThreadChecker();
executorThreadCheck.detachThread();
this.eventListener = eventListener; this.eventListener = eventListener;
InetAddress address; InetAddress address;
@ -83,7 +87,7 @@ public class TCPChannelClient {
* Disconnects the client if not already disconnected. This will fire the onTCPClose event. * Disconnects the client if not already disconnected. This will fire the onTCPClose event.
*/ */
public void disconnect() { public void disconnect() {
checkIfCalledOnValidThread(); executorThreadCheck.checkIsOnValidThread();
socket.disconnect(); socket.disconnect();
} }
@ -94,7 +98,7 @@ public class TCPChannelClient {
* @param message Message to be sent. * @param message Message to be sent.
*/ */
public void send(String message) { public void send(String message) {
checkIfCalledOnValidThread(); executorThreadCheck.checkIsOnValidThread();
socket.send(message); socket.send(message);
} }
@ -112,17 +116,6 @@ public class TCPChannelClient {
}); });
} }
/**
* Helper method for debugging purposes.
* Ensures that TCPChannelClient method is called on a looper thread.
*/
private void checkIfCalledOnValidThread() {
if (!executor.checkOnLooperThread()) {
throw new IllegalStateException(
"TCPChannelClient method is not called on valid thread");
}
}
/** /**
* Base class for server and client sockets. Contains a listening thread that will call * Base class for server and client sockets. Contains a listening thread that will call

View File

@ -19,7 +19,8 @@ import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
* Looper based executor class. * Looper based executor class. This is needed because WebSocketClient from autobanh requires the
* thread to have a looper. The class is used in WebSocketRTCClient/WebSocketChannelClient.
*/ */
public class LooperExecutor extends Thread implements Executor { public class LooperExecutor extends Thread implements Executor {
private static final String TAG = "LooperExecutor"; private static final String TAG = "LooperExecutor";

View File

@ -10,9 +10,6 @@
package org.appspot.apprtc; package org.appspot.apprtc;
import android.util.Log;
import org.appspot.apprtc.util.RobolectricLooperExecutor;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -56,8 +53,8 @@ public class DirectRTCClientTest {
clientEvents = mock(AppRTCClient.SignalingEvents.class); clientEvents = mock(AppRTCClient.SignalingEvents.class);
serverEvents = mock(AppRTCClient.SignalingEvents.class); serverEvents = mock(AppRTCClient.SignalingEvents.class);
client = new DirectRTCClient(clientEvents, new RobolectricLooperExecutor()); client = new DirectRTCClient(clientEvents);
server = new DirectRTCClient(serverEvents, new RobolectricLooperExecutor()); server = new DirectRTCClient(serverEvents);
} }
@Test @Test

View File

@ -10,7 +10,7 @@
package org.appspot.apprtc; package org.appspot.apprtc;
import org.appspot.apprtc.util.RobolectricLooperExecutor;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -21,6 +21,11 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog; import org.robolectric.shadows.ShadowLog;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@ -38,13 +43,14 @@ public class TCPChannelClientTest {
private static final int CONNECT_TIMEOUT = 100; private static final int CONNECT_TIMEOUT = 100;
private static final int SEND_TIMEOUT = 100; private static final int SEND_TIMEOUT = 100;
private static final int DISCONNECT_TIMEOUT = 100; private static final int DISCONNECT_TIMEOUT = 100;
private static final int TERMINATION_TIMEOUT = 1000;
private static final String TEST_MESSAGE_SERVER = "Hello, Server!"; private static final String TEST_MESSAGE_SERVER = "Hello, Server!";
private static final String TEST_MESSAGE_CLIENT = "Hello, Client!"; private static final String TEST_MESSAGE_CLIENT = "Hello, Client!";
@Mock TCPChannelClient.TCPChannelEvents serverEvents; @Mock TCPChannelClient.TCPChannelEvents serverEvents;
@Mock TCPChannelClient.TCPChannelEvents clientEvents; @Mock TCPChannelClient.TCPChannelEvents clientEvents;
private RobolectricLooperExecutor executor; private ExecutorService executor;
private TCPChannelClient server; private TCPChannelClient server;
private TCPChannelClient client; private TCPChannelClient client;
@ -55,15 +61,14 @@ public class TCPChannelClientTest {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
executor = new RobolectricLooperExecutor(); executor = Executors.newSingleThreadExecutor();
executor.requestStart();
} }
@After @After
public void tearDown() { public void tearDown() {
verifyNoMoreEvents(); verifyNoMoreEvents();
executor.executeAndWait(new Runnable() { executeAndWait(new Runnable() {
@Override @Override
public void run() { public void run() {
client.disconnect(); client.disconnect();
@ -72,9 +77,9 @@ public class TCPChannelClientTest {
}); });
// Stop the executor thread // Stop the executor thread
executor.requestStop(); executor.shutdown();
try { try {
executor.join(); executor.awaitTermination(TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) { } catch (InterruptedException e) {
fail(e.getMessage()); fail(e.getMessage());
} }
@ -112,7 +117,7 @@ public class TCPChannelClientTest {
public void testSendData() { public void testSendData() {
testConnectIPv4(); testConnectIPv4();
executor.executeAndWait(new Runnable() { executeAndWait(new Runnable() {
@Override @Override
public void run() { public void run() {
client.send(TEST_MESSAGE_SERVER); client.send(TEST_MESSAGE_SERVER);
@ -127,7 +132,7 @@ public class TCPChannelClientTest {
@Test @Test
public void testDisconnectServer() { public void testDisconnectServer() {
testConnectIPv4(); testConnectIPv4();
executor.executeAndWait(new Runnable() { executeAndWait(new Runnable() {
@Override @Override
public void run() { public void run() {
server.disconnect(); server.disconnect();
@ -141,7 +146,7 @@ public class TCPChannelClientTest {
@Test @Test
public void testDisconnectClient() { public void testDisconnectClient() {
testConnectIPv4(); testConnectIPv4();
executor.executeAndWait(new Runnable() { executeAndWait(new Runnable() {
@Override @Override
public void run() { public void run() {
client.disconnect(); client.disconnect();
@ -183,4 +188,15 @@ public class TCPChannelClientTest {
verifyNoMoreInteractions(serverEvents); verifyNoMoreInteractions(serverEvents);
verifyNoMoreInteractions(clientEvents); verifyNoMoreInteractions(clientEvents);
} }
/**
* Queues runnable to be run and waits for it to be executed by the executor thread
*/
public void executeAndWait(Runnable runnable) {
try {
executor.submit(runnable).get();
} catch (Exception e) {
fail(e.getMessage());
}
}
} }

View File

@ -1,118 +0,0 @@
/*
* Copyright 2016 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.appspot.apprtc.util;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import static org.junit.Assert.fail;
/**
* LooperExecutor that doesn't use Looper because its implementation in Robolectric is not suited
* for our needs. Also implements executeAndWait that can be used to wait until the runnable has
* been executed.
*/
public class RobolectricLooperExecutor extends LooperExecutor {
private volatile boolean running = false;
private static final int RUNNABLE_QUEUE_CAPACITY = 256;
private final BlockingQueue<Runnable> runnableQueue
= new ArrayBlockingQueue<>(RUNNABLE_QUEUE_CAPACITY);
private long threadId;
/**
* Executes the runnable passed to the constructor and sets isDone flag afterwards.
*/
private static class ExecuteAndWaitRunnable implements Runnable {
public boolean isDone = false;
private final Runnable runnable;
ExecuteAndWaitRunnable(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
runnable.run();
synchronized (this) {
isDone = true;
notifyAll();
}
}
}
@Override
public void run() {
threadId = Thread.currentThread().getId();
while (running) {
final Runnable runnable;
try {
runnable = runnableQueue.take();
} catch (InterruptedException e) {
if (running) {
fail(e.getMessage());
}
return;
}
runnable.run();
}
}
@Override
public synchronized void requestStart() {
if (running) {
return;
}
running = true;
start();
}
@Override
public synchronized void requestStop() {
running = false;
interrupt();
}
@Override
public synchronized void execute(Runnable runnable) {
try {
runnableQueue.put(runnable);
} catch (InterruptedException e) {
fail(e.getMessage());
}
}
/**
* Queues runnable to be run and waits for it to be executed by the executor thread
*/
public void executeAndWait(Runnable runnable) {
ExecuteAndWaitRunnable executeAndWaitRunnable = new ExecuteAndWaitRunnable(runnable);
execute(executeAndWaitRunnable);
synchronized (executeAndWaitRunnable) {
while (!executeAndWaitRunnable.isDone) {
try {
executeAndWaitRunnable.wait();
} catch (InterruptedException e) {
fail(e.getMessage());
}
}
}
}
@Override
public boolean checkOnLooperThread() {
return (Thread.currentThread().getId() == threadId);
}
}

View File

@ -13,13 +13,15 @@ package org.appspot.apprtc.test;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.appspot.apprtc.AppRTCClient.SignalingParameters; import org.appspot.apprtc.AppRTCClient.SignalingParameters;
import org.appspot.apprtc.PeerConnectionClient; import org.appspot.apprtc.PeerConnectionClient;
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionEvents; import org.appspot.apprtc.PeerConnectionClient.PeerConnectionEvents;
import org.appspot.apprtc.PeerConnectionClient.PeerConnectionParameters; import org.appspot.apprtc.PeerConnectionClient.PeerConnectionParameters;
import org.appspot.apprtc.util.LooperExecutor;
import org.webrtc.EglBase; import org.webrtc.EglBase;
import org.webrtc.IceCandidate; import org.webrtc.IceCandidate;
import org.webrtc.MediaCodecVideoEncoder; import org.webrtc.MediaCodecVideoEncoder;
@ -66,7 +68,7 @@ public class PeerConnectionClientTest extends InstrumentationTestCase
private EglBase eglBase; private EglBase eglBase;
// These are protected by their respective event objects. // These are protected by their respective event objects.
private LooperExecutor signalingExecutor; private ExecutorService signalingExecutor;
private boolean isClosed; private boolean isClosed;
private boolean isIceConnected; private boolean isIceConnected;
private SessionDescription localSdp; private SessionDescription localSdp;
@ -279,8 +281,7 @@ public class PeerConnectionClientTest extends InstrumentationTestCase
@Override @Override
public void setUp() { public void setUp() {
signalingExecutor = new LooperExecutor(); signalingExecutor = Executors.newSingleThreadExecutor();
signalingExecutor.requestStart();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
eglBase = EglBase.create(); eglBase = EglBase.create();
} }
@ -288,7 +289,7 @@ public class PeerConnectionClientTest extends InstrumentationTestCase
@Override @Override
public void tearDown() { public void tearDown() {
signalingExecutor.requestStop(); signalingExecutor.shutdown();
if (eglBase != null) { if (eglBase != null) {
eglBase.release(); eglBase.release();
} }