package org.ripple.power.speed; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class AsyncInputStream extends InputStream implements Runnable { private Thread thisThread; private InputStream is; private byte[] data; private boolean eof = false; private int mStreamIndex; private SpeedListener mNetworkSpeedListener; private int isIndex; private int index; final Lock lock = new ReentrantLock(); final Condition notEmpty = lock.newCondition(); public AsyncInputStream(InputStream inputStream, int size, int streamIndex, SpeedListener networkSpeedListener) { is = new BufferedInputStream(inputStream); data = new byte[size + 1]; mStreamIndex = streamIndex; mNetworkSpeedListener = networkSpeedListener; } public void start() { if (thisThread == null) { thisThread = new Thread(this); thisThread.setName("AsyncInputStream"); thisThread.setDaemon(true); thisThread.start(); } } public void stop() { if (thisThread != null) { thisThread = null; } } @Override public int read() throws IOException { byte[] buff = new byte[1]; int count = read(buff); if (count == 1) { return buff[0]; } else { return -1; } } @Override public int read(byte[] buffer) throws IOException { return read(buffer, 0, buffer.length); } @Override public int read(byte[] buffer, int offset, int length) throws IOException { int count = -1; lock.lock(); try { if (index == data.length - 1) { return -1; } if (isIndex == data.length - 1 && length > isIndex - index) { return -1; } while (index == isIndex) { try { notEmpty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } count = isIndex - index; if (length < count) { count = length; } System.arraycopy(data, index, buffer, offset, count); index += count; } finally { lock.unlock(); } return count; } @Override public void run() { try { int readed = 0; boolean endReached = false; float speed = -1; long t1 = System.currentTimeMillis(); while (readed < data.length && !endReached) { lock.lock(); try { int thisRead = is.read(data, readed, data.length - readed); if (thisRead > 0) { readed = readed + thisRead; isIndex = readed - 1; } else { endReached = true; } notEmpty.signal(); } finally { lock.unlock(); } } long t2 = System.currentTimeMillis(); long ms = t2 - t1; speed = (float) readed / ((float) ms / (float) 1000l); mNetworkSpeedListener.networkSpeed(0, mStreamIndex, speed); eof = true; } catch (IOException e) { e.printStackTrace(); } } @Override public long skip(long byteCount) throws IOException { byte[] buff = new byte[(int) byteCount]; int count = read(buff); return count; } public boolean isEof() { return eof; } }