FileDocCategorySizeDatePackage
Transport.javaAPI DocAndroid 5.1 API13784Thu Mar 12 22:22:42 GMT 2015com.android.accessorydisplay.common

Transport

public abstract class Transport extends Object
A simple message transport.

This object's interface is thread-safe, however incoming messages are always delivered on the {@link Looper} thread on which the transport was created.

Fields Summary
private static final int
MAX_INPUT_BUFFERS
private final Logger
mLogger
private final TransportHandler
mHandler
private final Object
mLock
private ByteBuffer
mOutputBuffer
private BufferPool
mInputBufferPool
private ReaderThread
mThread
private final android.util.SparseArray
mServices
Constructors Summary
public Transport(Logger logger, int maxPacketSize)


         
        mLogger = logger;
        mHandler = new TransportHandler();
        mOutputBuffer = ByteBuffer.allocate(maxPacketSize);
        mInputBufferPool = new BufferPool(
                maxPacketSize, Protocol.MAX_ENVELOPE_SIZE, MAX_INPUT_BUFFERS);
    
Methods Summary
private static voidcheckMessageId(int what)

        if (what < 0 || what > 0xffff) {
            throw new IllegalArgumentException("message id out of range: " + what);
        }
    
private static voidcheckServiceId(int service)

        if (service < 0 || service > 0xffff) {
            throw new IllegalArgumentException("service id out of range: " + service);
        }
    
public voidclose()
Closes the transport.

        synchronized (mLock) {
            if (mOutputBuffer != null) {
                if (mThread == null) {
                    ioClose();
                } else {
                    // If the thread was started then it will be responsible for
                    // closing the stream when it quits because it may currently
                    // be in the process of reading from the stream so we can't simply
                    // shut it down right now.
                    mThread.quit();
                }
                mOutputBuffer = null;
            }
        }
    
private voiddispatchMessageReceived(int service, int what, java.nio.ByteBuffer content)

        final Callback callback;
        synchronized (mLock) {
            callback = mServices.get(service);
        }
        if (callback != null) {
            callback.onMessageReceived(service, what, content);
        } else {
            mLogger.log("Discarding message " + what
                    + " for unregistered service " + service);
        }
    
public android.os.HandlergetHandler()
Gets the handler on the transport's thread.

        return mHandler;
    
public LoggergetLogger()
Gets the logger for debugging.

        return mLogger;
    
protected abstract voidioClose()

protected abstract intioRead(byte[] buffer, int offset, int count)

protected abstract voidioWrite(byte[] buffer, int offset, int count)

public voidregisterService(int service, com.android.accessorydisplay.common.Transport$Callback callback)
Registers a service and provides a callback to receive messages.

param
service The service id.
param
callback The callback to use.

        checkServiceId(service);
        if (callback == null) {
            throw new IllegalArgumentException("callback must not be null");
        }

        synchronized (mLock) {
            mServices.put(service, callback);
        }
    
public booleansendMessage(int service, int what, java.nio.ByteBuffer content)
Sends a message.

param
service The service to whom the message is addressed.
param
what The message type.
param
content The content, or null if there is none.
return
True if the message was sent successfully, false if an error occurred.

        checkServiceId(service);
        checkMessageId(what);

        try {
            synchronized (mLock) {
                if (mOutputBuffer == null) {
                    mLogger.logError("Send message failed because transport was closed.");
                    return false;
                }

                final byte[] outputArray = mOutputBuffer.array();
                final int capacity = mOutputBuffer.capacity();
                mOutputBuffer.clear();
                mOutputBuffer.putShort((short)service);
                mOutputBuffer.putShort((short)what);
                if (content == null) {
                    mOutputBuffer.putInt(0);
                } else {
                    final int contentLimit = content.limit();
                    int contentPosition = content.position();
                    int contentRemaining = contentLimit - contentPosition;
                    if (contentRemaining > Protocol.MAX_CONTENT_SIZE) {
                        throw new IllegalArgumentException("Message content too large: "
                                + contentRemaining + " > " + Protocol.MAX_CONTENT_SIZE);
                    }
                    mOutputBuffer.putInt(contentRemaining);
                    while (contentRemaining != 0) {
                        final int outputAvailable = capacity - mOutputBuffer.position();
                        if (contentRemaining <= outputAvailable) {
                            mOutputBuffer.put(content);
                            break;
                        }
                        content.limit(contentPosition + outputAvailable);
                        mOutputBuffer.put(content);
                        content.limit(contentLimit);
                        ioWrite(outputArray, 0, capacity);
                        contentPosition += outputAvailable;
                        contentRemaining -= outputAvailable;
                        mOutputBuffer.clear();
                    }
                }
                ioWrite(outputArray, 0, mOutputBuffer.position());
                return true;
            }
        } catch (IOException ex) {
            mLogger.logError("Send message failed: " + ex);
            return false;
        }
    
public voidstartReading()
Starts reading messages on a separate thread.

        synchronized (mLock) {
            if (mOutputBuffer == null) {
                throw new IllegalStateException("Transport has been closed");
            }

            mThread = new ReaderThread();
            mThread.start();
        }
    
public voidunregisterService(int service)
Unregisters a service.

param
service The service to unregister.

        checkServiceId(service);

        synchronized (mLock) {
            mServices.remove(service);
        }