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;
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.AlertDialog;
import android.app.FragmentTransaction;
@ -30,12 +25,16 @@ import android.view.Window;
import android.view.WindowManager.LayoutParams;
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.IceCandidate;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RendererCommon.ScalingType;
import org.webrtc.SessionDescription;
import org.webrtc.StatsReport;
import org.webrtc.RendererCommon.ScalingType;
import org.webrtc.SurfaceViewRenderer;
/**
@ -245,7 +244,7 @@ public class CallActivity extends Activity
appRtcClient = new WebSocketRTCClient(this, new LooperExecutor());
} else {
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.
roomConnectionParameters = new RoomConnectionParameters(
@ -314,9 +313,6 @@ public class CallActivity extends Activity
}
activityRunning = false;
rootEglBase.release();
if (cpuMonitor != null) {
cpuMonitor.release();
}
super.onDestroy();
}

View File

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

View File

@ -12,7 +12,6 @@ package org.appspot.apprtc;
import android.util.Log;
import org.appspot.apprtc.util.LooperExecutor;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -21,6 +20,8 @@ import org.webrtc.PeerConnection;
import org.webrtc.SessionDescription;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -52,7 +53,7 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
+ "(:(\\d+))?"
);
private final LooperExecutor executor;
private final ExecutorService executor;
private final SignalingEvents events;
private TCPChannelClient tcpClient;
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.
private ConnectionState roomState;
public DirectRTCClient(SignalingEvents events, LooperExecutor looperExecutor) {
public DirectRTCClient(SignalingEvents events) {
this.events = events;
executor = looperExecutor;
executor.requestStart();
executor = Executors.newSingleThreadExecutor();
roomState = ConnectionState.NEW;
}
@ -148,6 +148,7 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
tcpClient.disconnect();
tcpClient = null;
}
executor.shutdown();
}
@Override
@ -295,13 +296,11 @@ public class DirectRTCClient implements AppRTCClient, TCPChannelClient.TCPChanne
@Override
public void onTCPError(String description) {
reportError("TCP connection error: " + description);
executor.requestStop();
}
@Override
public void onTCPClose() {
events.onChannelClose();
executor.requestStop();
}
// --------------------------------------------------------------------

View File

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

View File

@ -12,7 +12,7 @@ package org.appspot.apprtc;
import android.util.Log;
import org.appspot.apprtc.util.LooperExecutor;
import org.webrtc.ThreadUtils;
import java.io.BufferedReader;
import java.io.IOException;
@ -22,6 +22,7 @@ import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
/**
* Replacement for WebSocketChannelClient for direct communication between two IP addresses. Handles
@ -34,7 +35,8 @@ import java.net.UnknownHostException;
public class 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 TCPSocket socket;
@ -58,8 +60,10 @@ public class TCPChannelClient {
* @param port Port to listen on or connect to.
*/
public TCPChannelClient(
LooperExecutor executor, TCPChannelEvents eventListener, String ip, int port) {
ExecutorService executor, TCPChannelEvents eventListener, String ip, int port) {
this.executor = executor;
executorThreadCheck = new ThreadUtils.ThreadChecker();
executorThreadCheck.detachThread();
this.eventListener = eventListener;
InetAddress address;
@ -83,7 +87,7 @@ public class TCPChannelClient {
* Disconnects the client if not already disconnected. This will fire the onTCPClose event.
*/
public void disconnect() {
checkIfCalledOnValidThread();
executorThreadCheck.checkIsOnValidThread();
socket.disconnect();
}
@ -94,7 +98,7 @@ public class TCPChannelClient {
* @param message Message to be sent.
*/
public void send(String message) {
checkIfCalledOnValidThread();
executorThreadCheck.checkIsOnValidThread();
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

View File

@ -19,7 +19,8 @@ import java.util.List;
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 {
private static final String TAG = "LooperExecutor";