Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4b6e492 authored by Jaikumar Ganesh's avatar Jaikumar Ganesh
Browse files

Retry rfcomm socket connections after link key exchange error.

If the devices were paired before, but unpaired on the
remote end, it will return an error (when sending a file)for the auth
request for the socket connection. Link keys will get exchanged
but we need to retry the socket connection. There is no good way to
inform this socket asking it to retry apart from
a delayed retry. The socket is opened at the kernel level
but the link key retrys happen at the Bluez userspace level.

Note: This is a temporary change, once the new mgmt interface comes
up in Bluez, we wouldn't need this.

Change-Id: Ifbd93d7f69b93515dda6c6f4ad2796853f9d5841
parent 3a59b70b
Loading
Loading
Loading
Loading
+55 −31
Original line number Diff line number Diff line
@@ -72,11 +72,13 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch

    private static final boolean V = Constants.VERBOSE;

    public static final int RFCOMM_ERROR = 10;
    private static final int RFCOMM_ERROR = 10;

    public static final int RFCOMM_CONNECTED = 11;
    private static final int RFCOMM_CONNECTED = 11;

    public static final int SDP_RESULT = 12;
    private static final int SDP_RESULT = 12;

    private static final int SOCKET_ERROR_RETRY = 13;

    private static final int CONNECT_WAIT_TIMEOUT = 45000;

@@ -84,6 +86,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch

    private static final short OPUSH_UUID16 = 0x1105;

    private static final String SOCKET_LINK_KEY_ERROR = "Invalid exchange";

    private Context mContext;

    private BluetoothAdapter mAdapter;
@@ -145,7 +149,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                        // ignore
                    }
                    if (msg.arg1 > 0) {
                        mConnectThread = new SocketConnectThread(mBatch.mDestination, msg.arg1);
                        mConnectThread = new
                            SocketConnectThread(mBatch.mDestination, msg.arg1, false);
                        mConnectThread.start();
                    } else {
                        /* SDP query fail case */
@@ -155,29 +160,34 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                    }

                    break;

                case SOCKET_ERROR_RETRY:
                    mConnectThread = new
                        SocketConnectThread((BluetoothDevice)msg.obj, msg.arg1, true);
                    mConnectThread.start();
                    break;
                case RFCOMM_ERROR:
                    /*
                    * RFCOMM connect fail is for outbound share only! Mark batch
                    * failed, and all shares in batch failed
                    */
                case RFCOMM_ERROR:
                    if (V) Log.v(TAG, "receive RFCOMM_ERROR msg");
                    mConnectThread = null;
                    markBatchFailed(BluetoothShare.STATUS_CONNECTION_ERROR);
                    mBatch.mStatus = Constants.BATCH_STATUS_FAILED;

                    break;
                case RFCOMM_CONNECTED:
                    /*
                    * RFCOMM connected is for outbound share only! Create
                    * BluetoothOppObexClientSession and start it
                    */
                case RFCOMM_CONNECTED:
                    if (V) Log.v(TAG, "Transfer receive RFCOMM_CONNECTED msg");
                    mConnectThread = null;
                    mTransport = (ObexTransport)msg.obj;
                    startObexSession();

                    break;
                case BluetoothOppObexSession.MSG_SHARE_COMPLETE:
                    /*
                    * Put next share if available,or finish the transfer.
                    * For outbound session, call session.addShare() to send next file,
@@ -185,7 +195,6 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                    * For inbounds session, do nothing. If there is next file to receive,it
                    * will be notified through onShareAdded()
                    */
                case BluetoothOppObexSession.MSG_SHARE_COMPLETE:
                    BluetoothOppShareInfo info = (BluetoothOppShareInfo)msg.obj;
                    if (V) Log.v(TAG, "receive MSG_SHARE_COMPLETE for info " + info.mId);
                    if (mBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
@@ -203,11 +212,11 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                        }
                    }
                    break;
                case BluetoothOppObexSession.MSG_SESSION_COMPLETE:
                    /*
                    * Handle session completed status Set batch status to
                    * finished
                    */
                case BluetoothOppObexSession.MSG_SESSION_COMPLETE:
                    BluetoothOppShareInfo info1 = (BluetoothOppShareInfo)msg.obj;
                    if (V) Log.v(TAG, "receive MSG_SESSION_COMPLETE for batch " + mBatch.mId);
                    mBatch.mStatus = Constants.BATCH_STATUS_FINISHED;
@@ -217,8 +226,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                    tickShareStatus(info1);
                    break;

                /* Handle the error state of an Obex session */
                case BluetoothOppObexSession.MSG_SESSION_ERROR:
                    /* Handle the error state of an Obex session */
                    if (V) Log.v(TAG, "receive MSG_SESSION_ERROR for batch " + mBatch.mId);
                    BluetoothOppShareInfo info2 = (BluetoothOppShareInfo)msg.obj;
                    mSession.stop();
@@ -586,6 +595,8 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch

        private BluetoothSocket btSocket = null;

        private boolean mRetry = false;

        /* create a TCP socket */
        public SocketConnectThread(String host, int port, int dummy) {
            super("Socket Connect Thread");
@@ -596,12 +607,14 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
        }

        /* create a Rfcomm Socket */
        public SocketConnectThread(BluetoothDevice device, int channel) {
        public SocketConnectThread(BluetoothDevice device, int channel, boolean
                retry) {
            super("Socket Connect Thread");
            this.device = device;
            this.host = null;
            this.channel = channel;
            isConnected = false;
            mRetry = retry;
        }

        public void interrupt() {
@@ -701,10 +714,21 @@ public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatch
                    mSessionHandler.obtainMessage(RFCOMM_CONNECTED, transport).sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "Rfcomm socket connect exception");
                    // If the devices were paired before, but unpaired on the
                    // remote end, it will return an error for the auth request
                    // for the socket connection. Link keys will get exchanged
                    // again, but we need to retry. There is no good way to
                    // inform this socket asking it to retry apart from a blind
                    // delayed retry.
                    if (mRetry) {
                        BluetoothOppPreference.getInstance(mContext)
                                .removeChannel(device, OPUSH_UUID16);
                        markConnectionFailed(btSocket);
                    return;
                    } else if (e.getMessage().equals(SOCKET_LINK_KEY_ERROR)) {
                        Message msg = mSessionHandler.obtainMessage(SOCKET_ERROR_RETRY,
                                channel, -1, device);
                        mSessionHandler.sendMessageDelayed(msg, 2500);
                    }
                }
            }
        }