summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCalvin Huang <calhuang@google.com>2020-05-20 06:43:36 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-05-20 06:43:36 +0000
commita9994028a88c4b2a693e7de15a15446ffb73f6d1 (patch)
treed39c199c499c31dabb9f50de34e5da3c84210673
parent6b3b05ece8dfc786927b30406a1724e04a54895b (diff)
parent66e02249efa278b871e5d2870d946c6ae7c25ca9 (diff)
downloadplatform_packages_apps_Car_Cluster-a9994028a88c4b2a693e7de15a15446ffb73f6d1.tar.gz
platform_packages_apps_Car_Cluster-a9994028a88c4b2a693e7de15a15446ffb73f6d1.tar.bz2
platform_packages_apps_Car_Cluster-a9994028a88c4b2a693e7de15a15446ffb73f6d1.zip
Remove NetworkedVirtualDisplay am: 66e02249ef
Change-Id: I6e66593b3237702d1558dd5f0ef646ac915d705f
-rw-r--r--src/android/car/cluster/ClusterDisplayProvider.java16
-rw-r--r--src/android/car/cluster/NetworkedVirtualDisplay.java452
-rw-r--r--src/android/car/cluster/PipeThread.java81
-rw-r--r--src/android/car/cluster/SenderThread.java47
-rw-r--r--src/android/car/cluster/SocketThread.java86
5 files changed, 2 insertions, 680 deletions
diff --git a/src/android/car/cluster/ClusterDisplayProvider.java b/src/android/car/cluster/ClusterDisplayProvider.java
index e1ee495..66329a4 100644
--- a/src/android/car/cluster/ClusterDisplayProvider.java
+++ b/src/android/car/cluster/ClusterDisplayProvider.java
@@ -36,10 +36,7 @@ import java.util.List;
* This class provides a display for instrument cluster renderer.
* <p>
* By default it will try to provide physical secondary display if it is connected, if secondary
- * display is not connected during creation of this class then it will start networked virtual
- * display and listens for incoming connections.
- *
- * @see {@link NetworkedVirtualDisplay}
+ * display is not connected during creation of this class then it will throw a IllegalStateException
*/
public class ClusterDisplayProvider {
private static final String TAG = "Cluster.DisplayProvider";
@@ -51,7 +48,6 @@ public class ClusterDisplayProvider {
private final DisplayListener mListener;
private final DisplayManager mDisplayManager;
- private NetworkedVirtualDisplay mNetworkedVirtualDisplay;
private int mClusterDisplayId = -1;
ClusterDisplayProvider(Context context, DisplayListener clusterDisplayListener) {
@@ -80,8 +76,7 @@ public class ClusterDisplayProvider {
mListener.onDisplayAdded(clusterDisplay.getDisplayId());
trackClusterDisplay(null /* no need to track display by name */);
} else {
- Log.i(TAG, "No physical cluster display found, starting network display");
- setupNetworkDisplay(context);
+ throw new IllegalStateException("ClusterDisplay is mandatory");
}
}
@@ -99,13 +94,6 @@ public class ClusterDisplayProvider {
throw new IllegalStateException("Can't find the OccupantZoneInfo for driver");
}
- private void setupNetworkDisplay(Context context) {
- mNetworkedVirtualDisplay = new NetworkedVirtualDisplay(context,
- NETWORKED_DISPLAY_WIDTH, NETWORKED_DISPLAY_HEIGHT, NETWORKED_DISPLAY_DPI);
- String displayName = mNetworkedVirtualDisplay.start();
- trackClusterDisplay(displayName);
- }
-
private void trackClusterDisplay(@Nullable String displayName) {
mDisplayManager.registerDisplayListener(new DisplayListener() {
@Override
diff --git a/src/android/car/cluster/NetworkedVirtualDisplay.java b/src/android/car/cluster/NetworkedVirtualDisplay.java
deleted file mode 100644
index 831f61e..0000000
--- a/src/android/car/cluster/NetworkedVirtualDisplay.java
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.car.cluster;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
-import android.hardware.display.VirtualDisplay;
-import android.media.MediaCodec;
-import android.media.MediaCodec.BufferInfo;
-import android.media.MediaCodec.CodecException;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecProfileLevel;
-import android.media.MediaFormat;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-import android.view.Display;
-import android.view.Surface;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.util.UUID;
-
-/**
- * This class encapsulates all work related to managing networked virtual display.
- * <p>
- * It opens a socket and listens on port {@code PORT} for connections, or the emulator pipe. Once
- * connection is established it creates virtual display and media encoder and starts streaming video
- * to that socket. If the receiving part is disconnected, it will keep port open and virtual
- * display won't be destroyed.
- */
-public class NetworkedVirtualDisplay {
- private static final String TAG = "Cluster." + NetworkedVirtualDisplay.class.getSimpleName();
-
- private final String mUniqueId = UUID.randomUUID().toString();
-
- private final DisplayManager mDisplayManager;
- private final int mWidth;
- private final int mHeight;
- private final int mDpi;
-
- private static final int FPS = 25;
- private static final int BITRATE = 6144000;
- private static final String MEDIA_FORMAT_MIMETYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
-
- public static final int MSG_START = 0;
- public static final int MSG_STOP = 1;
- public static final int MSG_SEND_FRAME = 2;
-
- private static final String PIPE_NAME = "pipe:qemud:carCluster";
- private static final String PIPE_DEVICE = "/dev/qemu_pipe";
-
- // Constants shared with emulator in car-cluster-widget.cpp
- public static final int PIPE_START = 1;
- public static final int PIPE_STOP = 2;
-
- private static final int PORT = 5151;
-
- private SenderThread mActiveThread;
- private HandlerThread mBroadcastThread = new HandlerThread("BroadcastThread");
-
- private VirtualDisplay mVirtualDisplay;
- private MediaCodec mVideoEncoder;
- private Handler mHandler;
- private byte[] mBuffer = null;
- private int mLastFrameLength = 0;
-
- private final DebugCounter mCounter = new DebugCounter();
-
- NetworkedVirtualDisplay(Context context, int width, int height, int dpi) {
- mDisplayManager = context.getSystemService(DisplayManager.class);
- mWidth = width;
- mHeight = height;
- mDpi = dpi;
-
- DisplayListener displayListener = new DisplayListener() {
- @Override
- public void onDisplayAdded(int i) {
- final Display display = mDisplayManager.getDisplay(i);
- if (display != null && getDisplayName().equals(display.getName())) {
- onVirtualDisplayReady(display);
- }
- }
-
- @Override
- public void onDisplayRemoved(int i) {}
-
- @Override
- public void onDisplayChanged(int i) {}
- };
-
- mDisplayManager.registerDisplayListener(displayListener, new Handler());
- }
-
- /**
- * Opens socket and creates virtual display asynchronously once connection established. Clients
- * of this class may subscribe to
- * {@link android.hardware.display.DisplayManager#registerDisplayListener(
- * DisplayListener, Handler)} to be notified when virtual display is created.
- * Note, that this method should be called only once.
- *
- * @return Unique display name associated with the instance of this class.
- *
- * @see {@link Display#getName()}
- *
- * @throws IllegalStateException thrown if networked display already started
- */
- public String start() {
- if (mBroadcastThread.isAlive()) {
- throw new IllegalStateException("Already started");
- }
-
- mBroadcastThread.start();
- mHandler = new BroadcastThreadHandler(mBroadcastThread.getLooper());
- mHandler.sendMessage(Message.obtain(mHandler, MSG_START));
- return getDisplayName();
- }
-
- public void release() {
- mHandler.sendMessage(Message.obtain(mHandler, MSG_STOP));
- mBroadcastThread.quitSafely();
-
- if (mVirtualDisplay != null) {
- mVirtualDisplay.setSurface(null);
- mVirtualDisplay.release();
- mVirtualDisplay = null;
- }
- }
-
- private String getDisplayName() {
- return "Cluster-" + mUniqueId;
- }
-
- private VirtualDisplay createVirtualDisplay() {
- Log.i(TAG, "createVirtualDisplay " + mWidth + "x" + mHeight +"@" + mDpi);
- return mDisplayManager.createVirtualDisplay(getDisplayName(), mWidth, mHeight, mDpi,
- null, 0 /* flags */, null, null );
- }
-
- private void onVirtualDisplayReady(Display display) {
- Log.i(TAG, "onVirtualDisplayReady, display: " + display);
- }
-
- private void startCasting(Handler handler) {
- Log.i(TAG, "Start casting...");
- if (mVideoEncoder != null) {
- Log.i(TAG, "Already started casting");
- return;
- }
- mVideoEncoder = createVideoStream(handler);
-
- if (mVirtualDisplay == null) {
- mVirtualDisplay = createVirtualDisplay();
- }
-
- mVirtualDisplay.setSurface(mVideoEncoder.createInputSurface());
- mVideoEncoder.start();
- Log.i(TAG, "Video encoder started");
- }
-
- private MediaCodec createVideoStream(Handler handler) {
- MediaCodec encoder;
- try {
- encoder = MediaCodec.createEncoderByType(MEDIA_FORMAT_MIMETYPE);
- } catch (IOException e) {
- Log.e(TAG, "Failed to create video encoder for " + MEDIA_FORMAT_MIMETYPE, e);
- return null;
- }
-
- encoder.setCallback(new MediaCodec.Callback() {
- @Override
- public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
- // Nothing to do
- }
-
- @Override
- public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index,
- @NonNull BufferInfo info) {
- mCounter.outputBuffers++;
- doOutputBufferAvailable(index, info);
- }
-
- @Override
- public void onError(@NonNull MediaCodec codec, @NonNull CodecException e) {
- Log.e(TAG, "onError, codec: " + codec, e);
- mCounter.bufferErrors++;
- stopCasting();
- startCasting(handler);
- }
-
- @Override
- public void onOutputFormatChanged(@NonNull MediaCodec codec,
- @NonNull MediaFormat format) {
- Log.i(TAG, "onOutputFormatChanged, codec: " + codec + ", format: " + format);
-
- }
- }, handler);
-
- configureVideoEncoder(encoder, mWidth, mHeight);
- return encoder;
- }
-
- private void doOutputBufferAvailable(int index, @NonNull BufferInfo info) {
- mHandler.removeMessages(MSG_SEND_FRAME);
-
- ByteBuffer encodedData = mVideoEncoder.getOutputBuffer(index);
- if (encodedData == null) {
- throw new RuntimeException("couldn't fetch buffer at index " + index);
- }
-
- if (info.size != 0) {
- encodedData.position(info.offset);
- encodedData.limit(info.offset + info.size);
- mLastFrameLength = encodedData.remaining();
- if (mBuffer == null || mBuffer.length < mLastFrameLength) {
- Log.i(TAG, "Allocating new buffer: " + mLastFrameLength);
- mBuffer = new byte[mLastFrameLength];
- }
- encodedData.get(mBuffer, 0, mLastFrameLength);
- mVideoEncoder.releaseOutputBuffer(index, false);
-
- // Send this frame asynchronously (avoiding blocking on the socket). We might miss
- // frames if the consumer is not fast enough, but this is acceptable.
- sendFrameAsync(0);
- } else {
- Log.e(TAG, "Skipping empty buffer");
- mVideoEncoder.releaseOutputBuffer(index, false);
- }
- }
-
- private void sendFrameAsync(long delayMs) {
- Message msg = mHandler.obtainMessage(MSG_SEND_FRAME);
- mHandler.sendMessageDelayed(msg, delayMs);
- }
-
- private void sendFrame(byte[] buf, int len) {
- if (mActiveThread != null) {
- mActiveThread.send(buf, len);
- }
- }
-
- private void stopCasting() {
- Log.i(TAG, "Stopping casting...");
-
- if (mVirtualDisplay != null) {
- Surface surface = mVirtualDisplay.getSurface();
- if (surface != null) surface.release();
- }
-
- if (mVideoEncoder != null) {
- // Releasing encoder as stop/start didn't work well (couldn't create or reuse input
- // surface).
- try {
- mVideoEncoder.stop();
- mVideoEncoder.release();
- } catch (IllegalStateException e) {
- // do nothing, already released
- }
- mVideoEncoder = null;
- }
- Log.i(TAG, "Casting stopped");
- }
-
- private class BroadcastThreadHandler extends Handler {
- private static final int MAX_FAIL_COUNT = 10;
- private int mFailConnectCounter;
-
- BroadcastThreadHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START:
- Log.i(TAG, "Received start message");
-
- // Make sure mActiveThread cannot start multiple times
- if (mActiveThread != null) {
- Log.w(TAG, "Trying to start a running thread. Race condition may exist");
- break;
- }
-
- // Failure to connect to either pipe or network returns null
- if (mActiveThread == null) {
- mActiveThread = tryPipeConnect();
- }
- if (mActiveThread == null) {
- mActiveThread = tryNetworkConnect();
- }
- if (mActiveThread == null) {
- // When failed attempt limit is reached, clean up and quit this thread.
- mFailConnectCounter++;
- if (mFailConnectCounter >= MAX_FAIL_COUNT) {
- Log.e(TAG, "Too many failed connection attempts; aborting");
- release();
- throw new RuntimeException("Abort after failed connection attempts");
- }
- mHandler.sendMessage(Message.obtain(mHandler, MSG_START));
- break;
- }
-
- try {
- mFailConnectCounter = 0;
- mCounter.clientsConnected++;
- mActiveThread.start();
- startCasting(this);
- } catch (Exception e) {
- Log.e(TAG, "Failed to start thread", e);
- Log.e(TAG, "DebugCounter: " + mCounter);
- }
- break;
-
- case MSG_STOP:
- Log.i(TAG, "Received stop message");
- stopCasting();
- mCounter.clientsDisconnected++;
- if (mActiveThread != null) {
- mActiveThread.close();
- try {
- mActiveThread.join();
- } catch (InterruptedException e) {
- Log.e(TAG, "Waiting for active thread to close failed", e);
- }
- mActiveThread = null;
- }
- break;
-
- case MSG_SEND_FRAME:
- if (mActiveThread == null) {
- // Stop the chaining signal if there's no client to send to
- break;
- }
- sendFrame(mBuffer, mLastFrameLength);
- // We will keep sending last frame every second as a heartbeat.
- sendFrameAsync(1000L);
- break;
- }
- }
-
- // Returns null if can't establish pipe connection
- // Otherwise returns the corresponding client thread
- private PipeThread tryPipeConnect() {
- try {
- RandomAccessFile pipe = new RandomAccessFile(PIPE_DEVICE, "rw");
- byte[] temp = new byte[PIPE_NAME.length() + 1];
- temp[PIPE_NAME.length()] = 0;
- System.arraycopy(PIPE_NAME.getBytes(), 0, temp, 0, PIPE_NAME.length());
- pipe.write(temp);
-
- // At this point, the pipe exists, so we will just wait for a start signal
- // This is in case pipe still sends leftover stops from last instantiation
- int signal = pipe.read();
- while (signal != PIPE_START) {
- Log.i(TAG, "Received non-start signal: " + signal);
- signal = pipe.read();
- }
- return new PipeThread(mHandler, pipe);
- } catch (IOException e) {
- Log.w(TAG, "Failed to establish pipe connection", e);
- return null;
- }
- }
-
- // Returns null if can't establish network connection
- // Otherwise returns the corresponding client thread
- private SocketThread tryNetworkConnect() {
- try {
- ServerSocket serverSocket = new ServerSocket(PORT);
- Log.i(TAG, "Server socket opened");
- Socket socket = serverSocket.accept();
- socket.setTcpNoDelay(true);
- socket.setKeepAlive(true);
- socket.setSoLinger(true, 0);
-
- InputStream inputStream = socket.getInputStream();
- OutputStream outputStream = socket.getOutputStream();
-
- return new SocketThread(mHandler, serverSocket, inputStream, outputStream);
- } catch (IOException e) {
- Log.w(TAG, "Failed to establish network connection", e);
- return null;
- }
- }
- }
-
- private static void configureVideoEncoder(MediaCodec codec, int width, int height) {
- MediaFormat format = MediaFormat.createVideoFormat(MEDIA_FORMAT_MIMETYPE, width, height);
-
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
- MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BITRATE);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, FPS);
- format.setInteger(MediaFormat.KEY_CAPTURE_RATE, FPS);
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
- format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1); // 1 second between I-frames
- format.setInteger(MediaFormat.KEY_LEVEL, CodecProfileLevel.AVCLevel31);
- format.setInteger(MediaFormat.KEY_PROFILE,
- MediaCodecInfo.CodecProfileLevel.AVCProfileBaseline);
-
- codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- }
-
- @Override
- public String toString() {
- return getClass() + "{"
- + ", receiver connected: " + (mActiveThread != null)
- + ", encoder: " + mVideoEncoder
- + ", virtualDisplay" + mVirtualDisplay
- + "}";
- }
-
- private static class DebugCounter {
- long outputBuffers;
- long bufferErrors;
- long clientsConnected;
- long clientsDisconnected;
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{"
- + "outputBuffers=" + outputBuffers
- + ", bufferErrors=" + bufferErrors
- + ", clientsConnected=" + clientsConnected
- + ", clientsDisconnected= " + clientsDisconnected
- + "}";
- }
- }
-}
diff --git a/src/android/car/cluster/PipeThread.java b/src/android/car/cluster/PipeThread.java
deleted file mode 100644
index a8f6308..0000000
--- a/src/android/car/cluster/PipeThread.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.car.cluster;
-import android.os.Handler;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * Thread that can send data to the emulator using a qemud service.
- */
-public class PipeThread extends SenderThread {
- private static final String TAG = "Cluster." + PipeThread.class.getSimpleName();
-
- private RandomAccessFile mPipe;
-
- /**
- * Creates instance of pipe thread that can write to given pipe file.
- *
- * @param handler {@link Handler} used to message broadcaster.
- * @param pipe {@link RandomAccessFile} file already connected to pipe.
- */
- PipeThread(Handler handler, RandomAccessFile pipe) {
- super(handler);
- mPipe = pipe;
- }
-
- public void run() {
- try {
- int signal = mPipe.read();
- while (signal != NetworkedVirtualDisplay.PIPE_STOP) {
- Log.i(TAG, "Received non-stop signal: " + signal);
- signal = mPipe.read();
- }
- restart();
- } catch (IOException e) {
- Log.e(TAG, "Failed to read from pipe");
- restart();
- }
- }
-
- @Override
- public void send(byte[] buf, int len) {
- try {
- // First sends the size prior to sending the data, since receiving side only sees
- // the size of the buffer, which could be significant larger than the actual data.
- mPipe.write(ByteBuffer.allocate(4)
- .order(ByteOrder.LITTLE_ENDIAN).putInt(len).array());
- mPipe.write(buf);
- } catch (IOException e) {
- Log.e(TAG, "Write to pipe failed");
- restart();
- }
- }
-
- @Override
- public void close() {
- try {
- mPipe.close();
- } catch (IOException e) {
- Log.e(TAG, "Failed to close pipe", e);
- }
- }
-}
-
diff --git a/src/android/car/cluster/SenderThread.java b/src/android/car/cluster/SenderThread.java
deleted file mode 100644
index de461e2..0000000
--- a/src/android/car/cluster/SenderThread.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.car.cluster;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-/**
- * This class serves as a template for sending to specific clients of the broadcaster.
- */
-public abstract class SenderThread extends Thread {
- private static final String TAG = "Cluster.SenderThread";
-
- private Handler mHandler;
-
- SenderThread(Handler handler) {
- mHandler = handler;
- }
-
- abstract void send(byte[] buf, int len);
- abstract void close();
-
- /**
- * Tells the broadcasting thread to stop and close everything in progress, and start over again.
- * It will kill the current instance of this thread, and produce a new one.
- */
- synchronized void restart() {
- if (mHandler.hasMessages(NetworkedVirtualDisplay.MSG_START)) return;
- Log.i(TAG, "Sending STOP and START msgs to NetworkedVirtualDisplay");
-
- mHandler.sendMessage(Message.obtain(mHandler, NetworkedVirtualDisplay.MSG_STOP));
- mHandler.sendMessage(Message.obtain(mHandler, NetworkedVirtualDisplay.MSG_START));
- }
-}
diff --git a/src/android/car/cluster/SocketThread.java b/src/android/car/cluster/SocketThread.java
deleted file mode 100644
index 7f1c61a..0000000
--- a/src/android/car/cluster/SocketThread.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.car.cluster;
-import android.os.Handler;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.ServerSocket;
-
-/**
- * The thread that will send data on an opened socket.
- */
-public class SocketThread extends SenderThread {
- private static final String TAG = "Cluster." + SocketThread.class.getSimpleName();
- private ServerSocket mServerSocket;
- private OutputStream mOutputStream;
- private InputStream mInputStream;
-
- /**
- * Create instance of thread that can write to given open socket.
- *
- * @param handler {@link Handler} used to message the broadcaster.
- * @param serverSocket {@link ServerSocket} should be already opened.
- * @param inputStream {@link InputStream} corresponding to opened socket.
- * @param outputStream {@link OutputStream} corresponding to opened socket.
- */
- SocketThread(Handler handler, ServerSocket serverSocket, InputStream inputStream,
- OutputStream outputStream) {
- super(handler);
- mServerSocket = serverSocket;
- mInputStream = inputStream;
- mOutputStream = outputStream;
- }
-
- public void run() {
- try {
- // This read should block until something disconnects (or something
- // similar) which should cause an exception, in which case we should
- // try to setup again and reconnect
- mInputStream.read();
- } catch (IOException e) {
- Log.e(TAG, "Socket thread disconnected.");
- }
- restart();
- }
-
- @Override
- public void send(byte[] buf, int len) {
- try {
- mOutputStream.write(buf, 0, len);
- } catch (IOException e) {
- Log.e(TAG, "Failed to write data to socket, retrying connection");
- restart();
- }
- }
-
- @Override
- public void close() {
- if (mServerSocket != null) {
- try {
- mServerSocket.close();
- } catch (IOException e) {
- Log.w(TAG, "Failed to close server socket, ignoring");
- }
- mServerSocket = null;
- }
- mInputStream = null;
- mOutputStream = null;
- }
-}
-