/*
 * Copyright (c) 2008-2009, Motorola, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Motorola, Inc. nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.android.bluetooth.opp;

import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.SdpOppOpsRecord;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.Process;
import android.util.Log;

import com.android.bluetooth.BluetoothObexTransport;

import java.io.File;
import java.io.IOException;

import javax.obex.ObexTransport;

/**
 * This class run an actual Opp transfer session (from connect target device to
 * disconnect)
 */
public class BluetoothOppTransfer implements BluetoothOppBatch.BluetoothOppBatchListener {
    private static final String TAG = "BtOppTransfer";

    private static final boolean D = Constants.DEBUG;

    private static final boolean V = Constants.VERBOSE;

    private static final int TRANSPORT_ERROR = 10;

    private static final int TRANSPORT_CONNECTED = 11;

    private static final int SOCKET_ERROR_RETRY = 13;

    private static final int CONNECT_WAIT_TIMEOUT = 45000;

    private static final int CONNECT_RETRY_TIME = 100;

    private static final String SOCKET_LINK_KEY_ERROR = "Invalid exchange";

    private Context mContext;

    private BluetoothAdapter mAdapter;

    private BluetoothDevice mDevice;

    private BluetoothOppBatch mBatch;

    private BluetoothOppObexSession mSession;

    private BluetoothOppShareInfo mCurrentShare;

    private ObexTransport mTransport;

    private HandlerThread mHandlerThread;

    private EventHandler mSessionHandler;

    private long mTimestamp;

    private class OppConnectionReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (D) {
                Log.d(TAG, " Action :" + action);
            }
            if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (device == null || mBatch == null || mCurrentShare == null) {
                    Log.e(TAG, "device : " + device + " mBatch :" + mBatch + " mCurrentShare :"
                            + mCurrentShare);
                    return;
                }
                try {
                    if (V) {
                        Log.v(TAG, "Device :" + device + "- OPP device: " + mBatch.mDestination
                                + " \n mCurrentShare.mConfirm == " + mCurrentShare.mConfirm);
                    }
                    if ((device.equals(mBatch.mDestination)) && (mCurrentShare.mConfirm
                            == BluetoothShare.USER_CONFIRMATION_PENDING)) {
                        if (V) {
                            Log.v(TAG, "ACTION_ACL_DISCONNECTED to be processed for batch: "
                                    + mBatch.mId);
                        }
                        // Remove the timeout message triggered earlier during Obex Put
                        mSessionHandler.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT);
                        // Now reuse the same message to clean up the session.
                        mSessionHandler.sendMessage(mSessionHandler.obtainMessage(
                                BluetoothOppObexSession.MSG_CONNECT_TIMEOUT));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
                ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
                if (D) {
                    Log.d(TAG, "Received UUID: " + uuid.toString());
                    Log.d(TAG, "expected UUID: " + BluetoothUuid.ObexObjectPush.toString());
                }
                if (uuid.equals(BluetoothUuid.ObexObjectPush)) {
                    int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1);
                    Log.d(TAG, " -> status: " + status);
                    BluetoothDevice device =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (mDevice == null) {
                        Log.w(TAG, "OPP SDP search, target device is null, ignoring result");
                        return;
                    }
                    if (!device.getAddress().equalsIgnoreCase(mDevice.getAddress())) {
                        Log.w(TAG, " OPP SDP search for wrong device, ignoring!!");
                        return;
                    }
                    SdpOppOpsRecord record =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
                    if (record == null) {
                        Log.w(TAG, " Invalid SDP , ignoring !!");
                        markConnectionFailed(null);
                        return;
                    }
                    mConnectThread =
                            new SocketConnectThread(mDevice, false, true, record.getL2capPsm());
                    mConnectThread.start();
                    mDevice = null;
                }
            }
        }
    }

    private OppConnectionReceiver mBluetoothReceiver;

    public BluetoothOppTransfer(Context context, BluetoothOppBatch batch,
            BluetoothOppObexSession session) {

        mContext = context;
        mBatch = batch;
        mSession = session;

        mBatch.registerListern(this);
        mAdapter = BluetoothAdapter.getDefaultAdapter();

    }

    public BluetoothOppTransfer(Context context, BluetoothOppBatch batch) {
        this(context, batch, null);
    }

    public int getBatchId() {
        return mBatch.mId;
    }

    /*
     * Receives events from mConnectThread & mSession back in the main thread.
     */
    private class EventHandler extends Handler {
        EventHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SOCKET_ERROR_RETRY:
                    mConnectThread = new SocketConnectThread((BluetoothDevice) msg.obj, true);

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

                    break;
                case TRANSPORT_CONNECTED:
                    /*
                    * RFCOMM connected is for outbound share only! Create
                    * BluetoothOppObexClientSession and start it
                    */
                    if (V) {
                        Log.v(TAG, "Transfer receive TRANSPORT_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,
                    * or call session.stop().
                    * For inbounds session, do nothing. If there is next file to receive,it
                    * will be notified through onShareAdded()
                    */
                    BluetoothOppShareInfo info = (BluetoothOppShareInfo) msg.obj;
                    if (V) {
                        Log.v(TAG, "receive MSG_SHARE_COMPLETE for info " + info.mId);
                    }
                    if (mBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
                        mCurrentShare = mBatch.getPendingShare();

                        if (mCurrentShare != null) {
                            /* we have additional share to process */
                            if (V) {
                                Log.v(TAG, "continue session for info " + mCurrentShare.mId
                                        + " from batch " + mBatch.mId);
                            }
                            processCurrentShare();
                        } else {
                            /* for outbound transfer, all shares are processed */
                            if (V) {
                                Log.v(TAG, "Batch " + mBatch.mId + " is done");
                            }
                            mSession.stop();
                        }
                    }
                    break;
                case BluetoothOppObexSession.MSG_SESSION_COMPLETE:
                    /*
                    * Handle session completed status Set batch status to
                    * finished
                    */
                    cleanUp();
                    BluetoothOppShareInfo info1 = (BluetoothOppShareInfo) msg.obj;
                    if (V) {
                        Log.v(TAG, "receive MSG_SESSION_COMPLETE for batch " + mBatch.mId);
                    }
                    mBatch.mStatus = Constants.BATCH_STATUS_FINISHED;
                    /*
                     * trigger content provider again to know batch status change
                     */
                    tickShareStatus(info1);
                    break;

                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);
                    }
                    cleanUp();
                    try {
                        BluetoothOppShareInfo info2 = (BluetoothOppShareInfo) msg.obj;
                        if (mSession != null) {
                            mSession.stop();
                        }
                        mBatch.mStatus = Constants.BATCH_STATUS_FAILED;
                        markBatchFailed(info2.mStatus);
                        tickShareStatus(mCurrentShare);
                    } catch (Exception e) {
                        Log.e(TAG, "Exception while handling MSG_SESSION_ERROR");
                        e.printStackTrace();
                    }
                    break;

                case BluetoothOppObexSession.MSG_SHARE_INTERRUPTED:
                    if (V) {
                        Log.v(TAG, "receive MSG_SHARE_INTERRUPTED for batch " + mBatch.mId);
                    }
                    BluetoothOppShareInfo info3 = (BluetoothOppShareInfo) msg.obj;
                    if (mBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
                        try {
                            if (mTransport == null) {
                                Log.v(TAG, "receive MSG_SHARE_INTERRUPTED but mTransport = null");
                            } else {
                                mTransport.close();
                            }
                        } catch (IOException e) {
                            Log.e(TAG, "failed to close mTransport");
                        }
                        if (V) {
                            Log.v(TAG, "mTransport closed ");
                        }
                        mBatch.mStatus = Constants.BATCH_STATUS_FAILED;
                        if (info3 != null) {
                            markBatchFailed(info3.mStatus);
                        } else {
                            markBatchFailed(BluetoothShare.STATUS_UNKNOWN_ERROR);
                        }
                        tickShareStatus(mCurrentShare);
                    }
                    break;

                case BluetoothOppObexSession.MSG_CONNECT_TIMEOUT:
                    if (V) {
                        Log.v(TAG, "receive MSG_CONNECT_TIMEOUT for batch " + mBatch.mId);
                    }
                    /* for outbound transfer, the block point is BluetoothSocket.write()
                     * The only way to unblock is to tear down lower transport
                     * */
                    if (mBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
                        try {
                            if (mTransport == null) {
                                Log.v(TAG, "receive MSG_SHARE_INTERRUPTED but mTransport = null");
                            } else {
                                mTransport.close();
                            }
                        } catch (IOException e) {
                            Log.e(TAG, "failed to close mTransport");
                        }
                        if (V) {
                            Log.v(TAG, "mTransport closed ");
                        }
                    } else {
                        /*
                         * For inbound transfer, the block point is waiting for
                         * user confirmation we can interrupt it nicely
                         */

                        // Remove incoming file confirm notification
                        NotificationManager nm = (NotificationManager) mContext.getSystemService(
                                Context.NOTIFICATION_SERVICE);
                        nm.cancel(mCurrentShare.mId);
                        // Send intent to UI for timeout handling
                        Intent in = new Intent(BluetoothShare.USER_CONFIRMATION_TIMEOUT_ACTION);
                        mContext.sendBroadcast(in);

                        markShareTimeout(mCurrentShare);
                    }
                    break;
            }
        }
    }

    private void markShareTimeout(BluetoothOppShareInfo share) {
        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + share.mId);
        ContentValues updateValues = new ContentValues();
        updateValues.put(BluetoothShare.USER_CONFIRMATION,
                BluetoothShare.USER_CONFIRMATION_TIMEOUT);
        mContext.getContentResolver().update(contentUri, updateValues, null, null);
    }

    private void markBatchFailed(int failReason) {
        synchronized (this) {
            try {
                wait(1000);
            } catch (InterruptedException e) {
                if (V) {
                    Log.v(TAG, "Interrupted waiting for markBatchFailed");
                }
            }
        }

        if (D) {
            Log.d(TAG, "Mark all ShareInfo in the batch as failed");
        }
        if (mCurrentShare != null) {
            if (V) {
                Log.v(TAG, "Current share has status " + mCurrentShare.mStatus);
            }
            if (BluetoothShare.isStatusError(mCurrentShare.mStatus)) {
                failReason = mCurrentShare.mStatus;
            }
            if (mCurrentShare.mDirection == BluetoothShare.DIRECTION_INBOUND
                    && mCurrentShare.mFilename != null) {
                new File(mCurrentShare.mFilename).delete();
            }
        }

        BluetoothOppShareInfo info = null;
        if (mBatch == null) {
            return;
        }
        info = mBatch.getPendingShare();
        while (info != null) {
            if (info.mStatus < 200) {
                info.mStatus = failReason;
                Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + info.mId);
                ContentValues updateValues = new ContentValues();
                updateValues.put(BluetoothShare.STATUS, info.mStatus);
                /* Update un-processed outbound transfer to show some info */
                if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
                    BluetoothOppSendFileInfo fileInfo =
                            BluetoothOppUtility.getSendFileInfo(info.mUri);
                    BluetoothOppUtility.closeSendFileInfo(info.mUri);
                    if (fileInfo.mFileName != null) {
                        updateValues.put(BluetoothShare.FILENAME_HINT, fileInfo.mFileName);
                        updateValues.put(BluetoothShare.TOTAL_BYTES, fileInfo.mLength);
                        updateValues.put(BluetoothShare.MIMETYPE, fileInfo.mMimetype);
                    }
                } else {
                    if (info.mStatus < 200 && info.mFilename != null) {
                        new File(info.mFilename).delete();
                    }
                }
                mContext.getContentResolver().update(contentUri, updateValues, null, null);
                Constants.sendIntentIfCompleted(mContext, contentUri, info.mStatus);
            }
            info = mBatch.getPendingShare();
        }

    }

    /*
     * NOTE
     * For outbound transfer
     * 1) Check Bluetooth status
     * 2) Start handler thread
     * 3) new a thread to connect to target device
     * 3.1) Try a few times to do SDP query for target device OPUSH channel
     * 3.2) Try a few seconds to connect to target socket
     * 4) After BluetoothSocket is connected,create an instance of RfcommTransport
     * 5) Create an instance of BluetoothOppClientSession
     * 6) Start the session and process the first share in batch
     * For inbound transfer
     * The transfer already has session and transport setup, just start it
     * 1) Check Bluetooth status
     * 2) Start handler thread
     * 3) Start the session and process the first share in batch
     */

    /**
     * Start the transfer
     */
    public void start() {
        /* check Bluetooth enable status */
        /*
         * normally it's impossible to reach here if BT is disabled. Just check
         * for safety
         */
        if (!mAdapter.isEnabled()) {
            Log.e(TAG, "Can't start transfer when Bluetooth is disabled for " + mBatch.mId);
            markBatchFailed(BluetoothShare.STATUS_UNKNOWN_ERROR);
            mBatch.mStatus = Constants.BATCH_STATUS_FAILED;
            return;
        }
        registerConnectionreceiver();
        if (mHandlerThread == null) {
            if (V) {
                Log.v(TAG, "Create handler thread for batch " + mBatch.mId);
            }
            mHandlerThread =
                    new HandlerThread("BtOpp Transfer Handler", Process.THREAD_PRIORITY_BACKGROUND);
            mHandlerThread.start();
            mSessionHandler = new EventHandler(mHandlerThread.getLooper());

            if (mBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
                /* for outbound transfer, we do connect first */
                startConnectSession();
            } else if (mBatch.mDirection == BluetoothShare.DIRECTION_INBOUND) {
                /*
                 * for inbound transfer, it's already connected, so we start
                 * OBEX session directly
                 */
                startObexSession();
            }
        }

    }

    /**
     * Stop the transfer
     */
    public void stop() {
        if (V) {
            Log.v(TAG, "stop");
        }
        if (mSession != null) {
            if (V) {
                Log.v(TAG, "Stop mSession");
            }
            mSession.stop();
        }

        cleanUp();
        if (mConnectThread != null) {
            try {
                mConnectThread.interrupt();
                if (V) {
                    Log.v(TAG, "waiting for connect thread to terminate");
                }
                mConnectThread.join();
            } catch (InterruptedException e) {
                if (V) {
                    Log.v(TAG, "Interrupted waiting for connect thread to join");
                }
            }
            mConnectThread = null;
        }
        // Prevent concurrent access
        synchronized (this) {
            if (mHandlerThread != null) {
                mHandlerThread.quit();
                mHandlerThread.interrupt();
                mHandlerThread = null;
            }
        }
    }

    private void startObexSession() {

        mBatch.mStatus = Constants.BATCH_STATUS_RUNNING;

        mCurrentShare = mBatch.getPendingShare();
        if (mCurrentShare == null) {
            /*
             * TODO catch this error
             */
            Log.e(TAG, "Unexpected error happened !");
            return;
        }
        if (V) {
            Log.v(TAG, "Start session for info " + mCurrentShare.mId + " for batch " + mBatch.mId);
        }

        if (mBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
            if (V) {
                Log.v(TAG, "Create Client session with transport " + mTransport.toString());
            }
            mSession = new BluetoothOppObexClientSession(mContext, mTransport);
        } else if (mBatch.mDirection == BluetoothShare.DIRECTION_INBOUND) {
            /*
             * For inbounds transfer, a server session should already exists
             * before BluetoothOppTransfer is initialized. We should pass in a
             * mSession instance.
             */
            if (mSession == null) {
                /** set current share as error */
                Log.e(TAG, "Unexpected error happened !");
                markBatchFailed(BluetoothShare.STATUS_UNKNOWN_ERROR);
                mBatch.mStatus = Constants.BATCH_STATUS_FAILED;
                return;
            }
            if (V) {
                Log.v(TAG, "Transfer has Server session" + mSession.toString());
            }
        }

        mSession.start(mSessionHandler, mBatch.getNumShares());
        processCurrentShare();
    }

    private void registerConnectionreceiver() {
        /*
         * OBEX channel need to be monitored for unexpected ACL disconnection
         * such as Remote Battery removal
         */
        synchronized (this) {
            try {
                if (mBluetoothReceiver == null) {
                    mBluetoothReceiver = new OppConnectionReceiver();
                    IntentFilter filter = new IntentFilter();
                    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
                    filter.addAction(BluetoothDevice.ACTION_SDP_RECORD);
                    mContext.registerReceiver(mBluetoothReceiver, filter);
                    if (V) {
                        Log.v(TAG, "Registered mBluetoothReceiver");
                    }
                }
            } catch (IllegalArgumentException e) {
                Log.e(TAG, "mBluetoothReceiver Registered already ", e);
            }
        }
    }

    private void processCurrentShare() {
        /* This transfer need user confirm */
        if (V) {
            Log.v(TAG, "processCurrentShare" + mCurrentShare.mId);
        }
        mSession.addShare(mCurrentShare);
        if (mCurrentShare.mConfirm == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED) {
            confirmStatusChanged();
        }
    }

    /**
     * Set transfer confirmed status. It should only be called for inbound
     * transfer
     */
    public void confirmStatusChanged() {
        /* unblock server session */
        final Thread notifyThread = new Thread("Server Unblock thread") {
            @Override
            public void run() {
                synchronized (mSession) {
                    mSession.unblock();
                    mSession.notify();
                }
            }
        };
        if (V) {
            Log.v(TAG, "confirmStatusChanged to unblock mSession" + mSession.toString());
        }
        notifyThread.start();
    }

    private void startConnectSession() {
        mDevice = mBatch.mDestination;
        if (!mBatch.mDestination.sdpSearch(BluetoothUuid.ObexObjectPush)) {
            if (D) {
                Log.d(TAG, "SDP failed, start rfcomm connect directly");
            }
            /* update bd address as sdp could not be started */
            mDevice = null;
            /* SDP failed, start rfcomm connect directly */
            mConnectThread = new SocketConnectThread(mBatch.mDestination, false, false, -1);
            mConnectThread.start();
        }
    }

    private SocketConnectThread mConnectThread;

    private class SocketConnectThread extends Thread {
        private final String mHost;

        private final BluetoothDevice mDevice;

        private final int mChannel;

        private int mL2cChannel = 0;

        private boolean mIsConnected;

        private long mTimestamp;

        private BluetoothSocket mBtSocket = null;

        private boolean mRetry = false;

        private boolean mSdpInitiated = false;

        private boolean mIsInterrupted = false;

        /* create a Rfcomm/L2CAP Socket */
        SocketConnectThread(BluetoothDevice device, boolean retry) {
            super("Socket Connect Thread");
            this.mDevice = device;
            this.mHost = null;
            this.mChannel = -1;
            mIsConnected = false;
            mRetry = retry;
            mSdpInitiated = false;
        }

        /* create a Rfcomm/L2CAP Socket */
        SocketConnectThread(BluetoothDevice device, boolean retry, boolean sdpInitiated,
                int l2capChannel) {
            super("Socket Connect Thread");
            this.mDevice = device;
            this.mHost = null;
            this.mChannel = -1;
            mIsConnected = false;
            mRetry = retry;
            mSdpInitiated = sdpInitiated;
            mL2cChannel = l2capChannel;
        }

        @Override
        public void interrupt() {
            if (D) {
                Log.d(TAG, "start interrupt :" + mBtSocket);
            }
            mIsInterrupted = true;
            if (mBtSocket != null) {
                try {
                    mBtSocket.close();
                } catch (IOException e) {
                    Log.v(TAG, "Error when close socket");
                }
            }
        }

        private void connectRfcommSocket() {
            if (V) {
                Log.v(TAG, "connectRfcommSocket");
            }
            try {
                if (mIsInterrupted) {
                    Log.d(TAG, "connectRfcommSocket interrupted");
                    markConnectionFailed(mBtSocket);
                    return;
                }
                mBtSocket = mDevice.createInsecureRfcommSocketToServiceRecord(
                        BluetoothUuid.ObexObjectPush.getUuid());
            } catch (IOException e1) {
                Log.e(TAG, "Rfcomm socket create error", e1);
                markConnectionFailed(mBtSocket);
                return;
            }
            try {
                mBtSocket.connect();

                if (V) {
                    Log.v(TAG,
                            "Rfcomm socket connection attempt took " + (System.currentTimeMillis()
                                    - mTimestamp) + " ms");
                }
                BluetoothObexTransport transport;
                transport = new BluetoothObexTransport(mBtSocket);

                BluetoothOppPreference.getInstance(mContext).setName(mDevice, mDevice.getName());

                if (V) {
                    Log.v(TAG, "Send transport message " + transport.toString());
                }

                mSessionHandler.obtainMessage(TRANSPORT_CONNECTED, transport).sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Rfcomm socket connect exception", e);
                // 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 && e.getMessage().equals(SOCKET_LINK_KEY_ERROR)) {
                    Message msg =
                            mSessionHandler.obtainMessage(SOCKET_ERROR_RETRY, -1, -1, mDevice);
                    mSessionHandler.sendMessageDelayed(msg, 1500);
                } else {
                    markConnectionFailed(mBtSocket);
                }
            }
        }

        @Override
        public void run() {
            mTimestamp = System.currentTimeMillis();
            if (D) {
                Log.d(TAG, "sdp initiated = " + mSdpInitiated + " l2cChannel :" + mL2cChannel);
            }
            // check if sdp initiated successfully for l2cap or not. If not
            // connect
            // directly to rfcomm
            if (!mSdpInitiated || mL2cChannel < 0) {
                /* sdp failed for some reason, connect on rfcomm */
                Log.d(TAG, "sdp not initiated, connecting on rfcomm");
                connectRfcommSocket();
                return;
            }

            /* Reset the flag */
            mSdpInitiated = false;

            /* Use BluetoothSocket to connect */
            try {
                if (mIsInterrupted) {
                    Log.e(TAG, "btSocket connect interrupted ");
                    markConnectionFailed(mBtSocket);
                    return;
                } else {
                    mBtSocket = mDevice.createInsecureL2capSocket(mL2cChannel);
                }
            } catch (IOException e1) {
                Log.e(TAG, "L2cap socket create error", e1);
                connectRfcommSocket();
                return;
            }
            try {
                mBtSocket.connect();
                if (V) {
                    Log.v(TAG, "L2cap socket connection attempt took " + (System.currentTimeMillis()
                            - mTimestamp) + " ms");
                }
                BluetoothObexTransport transport;
                transport = new BluetoothObexTransport(mBtSocket);
                BluetoothOppPreference.getInstance(mContext).setName(mDevice, mDevice.getName());
                if (V) {
                    Log.v(TAG, "Send transport message " + transport.toString());
                }
                mSessionHandler.obtainMessage(TRANSPORT_CONNECTED, transport).sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "L2cap socket connect exception", e);
                try {
                    mBtSocket.close();
                } catch (IOException e3) {
                    Log.e(TAG, "Bluetooth socket close error ", e3);
                }
                connectRfcommSocket();
                return;
            }
        }
    }

    private void markConnectionFailed(BluetoothSocket s) {
        if (V) {
            Log.v(TAG, "markConnectionFailed " + s);
        }
        try {
            if (s != null) {
                s.close();
            }
        } catch (IOException e) {
            if (V) {
                Log.e(TAG, "Error when close socket");
            }
        }
        mSessionHandler.obtainMessage(TRANSPORT_ERROR).sendToTarget();
        return;
    }

    /* update a trivial field of a share to notify Provider the batch status change */
    private void tickShareStatus(BluetoothOppShareInfo share) {
        if (share == null) {
            Log.d(TAG, "Share is null");
            return;
        }
        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + share.mId);
        ContentValues updateValues = new ContentValues();
        updateValues.put(BluetoothShare.DIRECTION, share.mDirection);
        mContext.getContentResolver().update(contentUri, updateValues, null, null);
    }

    /*
     * Note: For outbound transfer We don't implement this method now. If later
     * we want to support merging a later added share into an existing session,
     * we could implement here For inbounds transfer add share means it's
     * multiple receive in the same session, we should handle it to fill it into
     * mSession
     */

    /**
     * Process when a share is added to current transfer
     */
    @Override
    public void onShareAdded(int id) {
        BluetoothOppShareInfo info = mBatch.getPendingShare();
        if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) {
            mCurrentShare = mBatch.getPendingShare();
            /*
             * TODO what if it's not auto confirmed?
             */
            if (mCurrentShare != null && (
                    mCurrentShare.mConfirm == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED
                            || mCurrentShare.mConfirm
                            == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED)) {
                /* have additional auto confirmed share to process */
                if (V) {
                    Log.v(TAG, "Transfer continue session for info " + mCurrentShare.mId
                            + " from batch " + mBatch.mId);
                }
                processCurrentShare();
                confirmStatusChanged();
            }
        }
    }

    /*
     * NOTE We don't implement this method now. Now delete a single share from
     * the batch means the whole batch should be canceled. If later we want to
     * support single cancel, we could implement here For outbound transfer, if
     * the share is currently in transfer, cancel it For inbounds transfer,
     * delete share means the current receiving file should be canceled.
     */

    /**
     * Process when a share is deleted from current transfer
     */
    @Override
    public void onShareDeleted(int id) {

    }

    /**
     * Process when current transfer is canceled
     */
    @Override
    public void onBatchCanceled() {
        if (V) {
            Log.v(TAG, "Transfer on Batch canceled");
        }

        this.stop();
        mBatch.mStatus = Constants.BATCH_STATUS_FINISHED;
    }

    private void cleanUp() {
        synchronized (this) {
            try {
                if (mBluetoothReceiver != null) {
                    mContext.unregisterReceiver(mBluetoothReceiver);
                    mBluetoothReceiver = null;
                }
            } catch (Exception e) {
                Log.e(TAG, "Exception:unregisterReceiver");
                e.printStackTrace();
            }
        }
    }
}
