package android.media.midi;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
public final class MidiInputPort extends MidiReceiver implements Closeable {
private static final String TAG = "MidiInputPort";
private IMidiDeviceServer mDeviceServer;
private final IBinder mToken;
private final int mPortNumber;
private FileDescriptor mFileDescriptor;
private FileOutputStream mOutputStream;
private final CloseGuard mGuard = CloseGuard.get();
private boolean mIsClosed;
private final byte[] mBuffer = new byte[MidiPortImpl.MAX_PACKET_SIZE];
MidiInputPort(IMidiDeviceServer server, IBinder token,
FileDescriptor fd, int portNumber) {
super(MidiPortImpl.MAX_PACKET_DATA_SIZE);
mDeviceServer = server;
mToken = token;
mFileDescriptor = fd;
mPortNumber = portNumber;
mOutputStream = new FileOutputStream(fd);
mGuard.open("close");
}
MidiInputPort(FileDescriptor fd, int portNumber) {
this(null, null, fd, portNumber);
}
public final int getPortNumber() {
return mPortNumber;
}
@Override
public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
if (offset < 0 || count < 0 || offset + count > msg.length) {
throw new IllegalArgumentException("offset or count out of range");
}
if (count > MidiPortImpl.MAX_PACKET_DATA_SIZE) {
throw new IllegalArgumentException("count exceeds max message size");
}
synchronized (mBuffer) {
if (mOutputStream == null) {
throw new IOException("MidiInputPort is closed");
}
int length = MidiPortImpl.packData(msg, offset, count, timestamp, mBuffer);
mOutputStream.write(mBuffer, 0, length);
}
}
@Override
public void onFlush() throws IOException {
synchronized (mBuffer) {
if (mOutputStream == null) {
throw new IOException("MidiInputPort is closed");
}
int length = MidiPortImpl.packFlush(mBuffer);
mOutputStream.write(mBuffer, 0, length);
}
}
FileDescriptor claimFileDescriptor() {
synchronized (mGuard) {
FileDescriptor fd;
synchronized (mBuffer) {
fd = mFileDescriptor;
if (fd == null) return null;
IoUtils.closeQuietly(mOutputStream);
mFileDescriptor = null;
mOutputStream = null;
}
mIsClosed = true;
return fd;
}
}
IBinder getToken() {
return mToken;
}
IMidiDeviceServer getDeviceServer() {
return mDeviceServer;
}
@Override
public void close() throws IOException {
synchronized (mGuard) {
if (mIsClosed) return;
mGuard.close();
synchronized (mBuffer) {
if (mFileDescriptor != null) {
IoUtils.closeQuietly(mFileDescriptor);
mFileDescriptor = null;
}
if (mOutputStream != null) {
mOutputStream.close();
mOutputStream = null;
}
}
if (mDeviceServer != null) {
try {
mDeviceServer.closePort(mToken);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in MidiInputPort.close()");
}
}
mIsClosed = true;
}
}
@Override
protected void finalize() throws Throwable {
try {
if (mGuard != null) {
mGuard.warnIfOpen();
}
mDeviceServer = null;
close();
} finally {
super.finalize();
}
}
}