Android Open Accessory USB communication failing after sending large data packets

861 Views Asked by At

I have an android phone communicating with a Linux machine using AOA. The Linux machine is set up to initiate the connection, then wait for incoming data and echo it back to the phone unchanged. This works fine for small packets of data (less than 1024 bytes) from the phone. However, if I send exactly 1024 bytes, it appears to work from the Android end, but the computer never sees the packet, just any following ones that are smaller. If the phone attempts to send packets larger than 1024, these do get received by the computer, but the android phone will no longer be able to receive any packets from the computer. Further confusing the issue, this did work in the past, yet rolling back to earlier versions of the transmitting/receiving code on the phone doesn't seem to have any effect. The code on the computer has not been changed.

The android app checks for a USB accessory at start-up, and if one is found it starts a listener and sender thread. The sender thread waits on a blocking queue for outgoing packets, and sends them as soon as they are received. The listener thread continuously attempts to read from the input stream, which blocks until data is available. This is the code I use for setting up & running the threads:

private boolean openUSB(){
    mUSBManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    mAccessory = mUSBManager.getAccessoryList();
    if (mAccessory != null && mAccessory.length > 0) {
        mParcelFileDescriptor = mUSBManager.openAccessory(mAccessory[0]);
        mFileDescriptor = mParcelFileDescriptor.getFileDescriptor();

        mListener = new Thread() {
            public void run() {
                listenerThread();
            }

        };
        mListener.start();

        mSender = new Thread() {
            public void run() {
                senderThread();
            }

        };
        mSender.start();
        displayText("Connected to USB accessory");

        return true;
    } else {
        displayText("No USB accessory detected"); 
        return false;
    }
}

private void listenerThread(){

    byte packet[] = new byte[SDR_PREFIX_SIZE+SDR_HEADER_SIZE+SDR_MAX_PAYLOAD+SDR_CRC_SIZE];
    FileInputStream input = new FileInputStream(mFileDescriptor);
    try {
        ByteArrayOutputStream incoming = new ByteArrayOutputStream();
        displayText("Listener Started");
        while ( mFileDescriptor != null && input != null ) {
            int read = input.read(packet,0,packet.length);

            /* data in packet gets processed */
        }
    } catch ( Exception e) {
        displayText("Listener Exception - "+e.getMessage(),true);
    }
    displayText("Listener Exited");
}

private void senderThread(){

    displayText("sender started");
    FileOutputStream output=new FileOutputStream(mFileDescriptor);

    try {
        byte data[] = mTransmitQueue.take();
        while (data != null) {
            displayText("Sending packet " + packet + ", "+data.length + " bytes");
            output.write(data);

            data = mTransmitQueue.take();
        }

    } catch ( Exception e) {
        displayText("Sender Exception - "+e.getMessage(),true);
    }
}

In the past, I had issues getting the listener and sender to work, until I found out that some of the intermediate objects that were used to create the file streams were being garbage-collected, yet were still needed. I now store all those intermediate objects to member variables (mUSBManager, mAccessory, mParcelFileDescriptor, mFileDescriptor) to give them persistence. I suspect that this issue is something similar, but I haven't been able to make any headway. I have been beating my head on this issue without any success, and really hope that others will have some insight on what is causing this.

1

There are 1 best solutions below

0
On

I've found a work-around, expanding the buffer used for receiving data seems to fix the issue, even though the existing buffer was large enough for all packets. Increasing the buffer from 1524 to 2524 fixed the issue with incoming packets not being received. This is a kludgy solution, but it works.